क्या मैं एक स्क्रॉल दृश्य के लिए onScrollListener कर सकता हूं?


140

मैं HorizontalScrollViewएक लेआउट में उपयोग कर रहा हूं और मुझे स्क्रॉल की शुरुआत और अंत बिंदु तक पहुंचने वाले उपयोगकर्ता की पहचान करने की आवश्यकता है।

क्योंकि ListViewमैंने एक कोशिश की है onScrollListenerऔर स्क्रॉल का प्रारंभ और अंत बिंदु खोजना संभव है।

मैंने अपने में भी ऐसा करने की कोशिश की Scrollviewलेकिन यह संभव नहीं लगता। क्या कोई अन्य संभव तरीके हैं जो मुझे प्राप्त करने की आवश्यकता है।


3
हो सकता है। देखिए user2695685 का जवाब संक्षेप में निम्नलिखित कार्य onStartकरेंगे: hsv.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {@Override public void onScrollChanged() {Log.i(TAG,"scroll:"+hsv.getScrollX());}});onStart () में जहां hsvएक HorizontalScrollViewकाम है।
जॉनीलम्बदा

किसी को भी उपयोगी उत्तर स्वीकार करें..अन्यथा अपना उत्तर दें ..
रंजीथ कुमार

12
एंड्रॉइड में स्क्रॉलव्यू के साथ स्क्रॉल इवेंट का पता लगाना इतना मुश्किल क्यों है? यह नट्स इमो है।
काम किया

जवाबों:


389

व्यू कॉल के हर उदाहरण getViewTreeObserver()। अब जब का एक उदाहरण पकड़े ViewTreeObserver, आप OnScrollChangedListener()इसे विधि का उपयोग करके जोड़ सकते हैं addOnScrollChangedListener()

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

यह आपको प्रत्येक स्क्रॉलिंग घटना के बारे में पता करने देता है - लेकिन निर्देशांक के बिना। आप उन्हें श्रोता के भीतर getScrollY()या बाहर getScrollX()से प्राप्त कर सकते हैं ।

scrollView.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {
    @Override
    public void onScrollChanged() {
        int scrollY = rootScrollView.getScrollY(); // For ScrollView
        int scrollX = rootScrollView.getScrollX(); // For HorizontalScrollView
        // DO SOMETHING WITH THE SCROLL COORDINATES
    }
});

6
यह उत्तर सही होना चाहिए। hsv.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {@Override public void onScrollChanged() {Log.i(TAG,"scroll:"+hsv.getScrollX());}});onStart () जहां hsvएक HorizontalScrollViewकाम है। मुझे शक है कि स्क्रॉल स्क्रॉल के लिए भी यही काम होगा।
जॉनीलैम्बडा

3
बिल्कुल सही। यह सबसे अच्छा जवाब है। क्षैतिज क्षैतिज दृश्य को विस्तारित करने की आवश्यकता नहीं है। बस एक स्क्रॉल दृश्य के साथ परीक्षण किया गया, महान काम करता है: अंतिम स्क्रॉल दृश्य sv = (स्क्रॉल दृश्य) findViewById (R.id.scrollViewArticle); sv.getViewTreeObserver ()। addOnScrollChangedListener (नया दृश्यTreeObserver.OnScrollChangedListener) () {@Override public void onSrollChanged () {Log.d ("onScrollChanged Y", String.value-value.com
राफेल C

5
आपको सबसे पहले ViewTreeObserver.isAlive ()
M.Salomaa

7
उत्तर में नमूना कोड एक स्मृति रिसाव का परिचय देता है। चूंकि विधि है addऔर नहीं set, स्पष्ट रूप से हटाए जाने तक सभी श्रोताओं को बनाए रखा जाएगा। तो नमूने में एक श्रोता कार्यान्वयन के रूप में इस्तेमाल किया जाने वाला अनाम वर्ग लीक हो जाएगा (कुछ भी इसके साथ संदर्भित है, अर्थात बाहरी वर्ग)।
ब्रेट डंकेवेज

7
शायद एक गूंगा सवाल, लेकिन rootScrollView क्या है?
इकबाल

49

यह बहुत उपयोगी हो सकता है। के NestedScrollViewबजाय का उपयोग करें ScrollView। सपोर्ट लाइब्रेरी 23.1 ने एक परिचय OnScrollChangeListenerदिया NestedScrollView। तो आप ऐसा कुछ कर सकते हैं।

 myScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
        @Override
        public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
            Log.d("ScrollView","scrollX_"+scrollX+"_scrollY_"+scrollY+"_oldScrollX_"+oldScrollX+"_oldScrollY_"+oldScrollY);
            //Do something
        }
    });

2
निश्चित रूप से ट्रैक रखने से ज्यादा आसान है कि आपने श्रोता को getViewTreeObserver () के साथ जोड़ा है या नहीं। धन्यवाद!
एंथनी मिल्स

लेकिन क्षैतिज स्क्रॉल दृश्य के रूप में NestedScrollView का उपयोग कैसे करें? कैन्टन को कोई भी संसाधन नहीं मिल रहा है
GensaGames

क्या होगा यदि मैं क्षैतिज स्क्रॉल का उपयोग करना चाहता हूं?
निकिता आइकोनोव

7
@ dazed'n'confused NestedScrollViewसमर्थन लाइब्रेरी का हिस्सा है, इसकी setOnScrollChangeListenerविधि में न्यूनतम संस्करण की आवश्यकता नहीं है।
टॉम

4
नहीं करने के लिए भ्रमित होने Viewकी setOnScrollChangeListenerआवश्यकता है जो एपीआई स्तर 23 की आवश्यकता है
एंडर्स Ulln Febss

18

यहाँ एक व्युत्पन्न HoroscopeScrollView है जो मैंने स्क्रॉलिंग और स्क्रॉल एंडिंग के बारे में सूचनाओं को संभालने के लिए लिखा था। यह ठीक से हैंडल जब कोई उपयोगकर्ता सक्रिय रूप से बंद कर दिया है स्क्रॉल और जब यह पूरी तरह से decelerates के बाद एक उपयोगकर्ता जाना कर सकते हैं:

public class ObservableHorizontalScrollView extends HorizontalScrollView {
    public interface OnScrollListener {
        public void onScrollChanged(ObservableHorizontalScrollView scrollView, int x, int y, int oldX, int oldY);
        public void onEndScroll(ObservableHorizontalScrollView scrollView);
    }

    private boolean mIsScrolling;
    private boolean mIsTouching;
    private Runnable mScrollingRunnable;
    private OnScrollListener mOnScrollListener;

    public ObservableHorizontalScrollView(Context context) {
        this(context, null, 0);
    }

    public ObservableHorizontalScrollView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int action = ev.getAction();

        if (action == MotionEvent.ACTION_MOVE) {
            mIsTouching = true;
            mIsScrolling = true;
        } else if (action == MotionEvent.ACTION_UP) {
            if (mIsTouching && !mIsScrolling) {
                if (mOnScrollListener != null) {
                    mOnScrollListener.onEndScroll(this);
                }
            }

            mIsTouching = false;
        }

        return super.onTouchEvent(ev);
    }

    @Override
    protected void onScrollChanged(int x, int y, int oldX, int oldY) {
        super.onScrollChanged(x, y, oldX, oldY);

        if (Math.abs(oldX - x) > 0) {
            if (mScrollingRunnable != null) {
                removeCallbacks(mScrollingRunnable);
            }

            mScrollingRunnable = new Runnable() {
                public void run() {
                    if (mIsScrolling && !mIsTouching) {
                        if (mOnScrollListener != null) {
                            mOnScrollListener.onEndScroll(ObservableHorizontalScrollView.this);
                        }
                    }

                    mIsScrolling = false;
                    mScrollingRunnable = null;
                }
            };

            postDelayed(mScrollingRunnable, 200);
        }

        if (mOnScrollListener != null) {
            mOnScrollListener.onScrollChanged(this, x, y, oldX, oldY);
        }
    }

    public OnScrollListener getOnScrollListener() {
        return mOnScrollListener;
    }

    public void setOnScrollListener(OnScrollListener mOnEndScrollListener) {
        this.mOnScrollListener = mOnEndScrollListener;
    }

}

1
ऐसा लगता है कि यह ViewTreeObserver विधि का उपयोग करने से बेहतर है। सिर्फ इसलिए कि जब आपके पास एक गतिविधि होती है, जहां आपके पास कई टुकड़े होते हैं (उदाहरण के लिए स्लाइडिंग टैब के साथ 3 टुकड़े), सूची दृश्य और स्क्रॉल दृश्य के साथ और आपको विशिष्ट दृश्य के लिए घटनाओं को पंजीकृत करने की आवश्यकता होती है। जबकि अगर ViewTreeObserver पंजीकृत है, तो यह घटनाओं को आग लगा देगा भले ही यह सक्रिय दृश्य न हो।
टॉरस्टेन ओजापर्व

3
@ZaBlanc - क्या आप मुझे क्रॉल कर सकते हैं कि इस कक्षा और श्रोताओं को मेरी गतिविधि से कैसे जोड़ा जाए, जो स्क्रॉलव्यू रखती है? मैंने इसे ठीक-ठीक लागू किया है, लेकिन श्रोता अभी तक किसी भी मूल्य को वापस नहीं करेंगे।
एडमंड तमस

यह वास्तव में काम करता है! और इसके लिए sdk> 23 की कोई आवश्यकता नहीं है :)
मतान दहन

5

यदि आप किसी दृश्य की स्क्रॉल स्थिति जानना चाहते हैं, तो आप व्यू क्लास पर निम्नलिखित एक्सटेंशन फ़ंक्शन का उपयोग कर सकते हैं:

fun View?.onScroll(callback: (x: Int, y: Int) -> Unit) {
    var oldX = 0
    var oldY = 0
    this?.viewTreeObserver?.addOnScrollChangedListener {
        if (oldX != scrollX || oldY != scrollY) {
            callback(scrollX, scrollY)
            oldX = scrollX
            oldY = scrollY
        }
    }
}

5

आप उपयोग कर सकते हैं NestedScrollViewके बजाय ScrollView। हालाँकि, जब एक कोटलिन लैंबडा का उपयोग करते हैं, तो यह आपको पता नहीं चलेगा कि व्यू में NestedScrollView की setOnScrollChangeListenerजगह है (जो कि एपीआई स्तर 23 है)। आप पहले पैरामीटर को NestedScrollView के रूप में निर्दिष्ट करके इसे ठीक कर सकते हैं।

nestedScrollView.setOnScrollChangeListener { _: NestedScrollView, scrollX: Int, scrollY: Int, _: Int, _: Int ->
    Log.d("ScrollView", "Scrolled to $scrollX, $scrollY")
}

यह स्वीकृत उत्तर होना चाहिए क्योंकि एक viewTreeObserver का उपयोग करने की विधि स्मृति लीक का कारण बनती है और इसे मैन्युअल रूप से हटा दिया जाना चाहिए या फिर कई स्क्रॉल पर्यवेक्षक जोड़े जाएंगे।
रे ली

1

आप एक कस्टम स्क्रॉलव्यू क्लास को परिभाषित कर सकते हैं, और इस तरह स्क्रॉल करते समय एक इंटरफ़ेस जोड़ सकते हैं:

public class ScrollChangeListenerScrollView extends HorizontalScrollView {


private MyScrollListener mMyScrollListener;

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

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

public ScrollChangeListenerScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}


public void setOnMyScrollListener(MyScrollListener myScrollListener){
    this.mMyScrollListener = myScrollListener;
}


@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    super.onScrollChanged(l, t, oldl, oldt);
    if(mMyScrollListener!=null){
        mMyScrollListener.onScrollChange(this,l,t,oldl,oldt);
    }

}

public interface MyScrollListener {
    void onScrollChange(View view,int scrollX,int scrollY,int oldScrollX, int oldScrollY);
}

}

0
    // --------Start Scroll Bar Slide--------
    final HorizontalScrollView xHorizontalScrollViewHeader = (HorizontalScrollView) findViewById(R.id.HorizontalScrollViewHeader);
    final HorizontalScrollView xHorizontalScrollViewData = (HorizontalScrollView) findViewById(R.id.HorizontalScrollViewData);
    xHorizontalScrollViewData.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            int scrollX; int scrollY;
            scrollX=xHorizontalScrollViewData.getScrollX();
            scrollY=xHorizontalScrollViewData.getScrollY();
            xHorizontalScrollViewHeader.scrollTo(scrollX, scrollY);
        }
    });
    // ---------End Scroll Bar Slide---------

कृपया आपको कोड का समर्थन करने के लिए कुछ विवरण जोड़ने की कोशिश करें जिससे हर कोई बल्लेबाज को समझ लेगा
अनिरुद्ध दास

यह कोड एक अन्य उत्तर के समान है , है ना?
सर्गि
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.