অ্যান্ড্রয়েড: স্ক্রোলভিউ যখন স্ক্রোলিং বন্ধ করে দেয় তখন সনাক্ত করুন


87

আমি ScrollViewঅ্যান্ড্রয়েডে একটি ব্যবহার করছি এবং যেখানে এর দৃশ্যমান অংশটি এর ScrollViewঅভ্যন্তরের কোষগুলির মধ্যে একটির মতো আকারের Scrollview। প্রতিটি "ঘর" একই উচ্চতা। সুতরাং আমি যা করার চেষ্টা করছি তা হ'ল ScrollViewস্ক্রোল হওয়ার পরে পজিশনে পড়ে ।

বর্তমানে আমি সনাক্ত করছি যে কখন ব্যবহারকারীটি স্পর্শ করেছে ScrollViewএবং কখন তারা সেখান থেকে স্ক্রোলিং এবং এটির কাজ শুরু করেছে, তবে এটি বেশ বগল। এটির জন্যও কাজ করা উচিত যখন ব্যবহারকারী কেবল এটিতে ক্লিক করে এবং এটি স্ক্রোল করে এবং হ্রাস পায়।

আইফোনে একটি ফাংশন রয়েছে যা এর মতো কিছু didDecelerateএবং সেখানে যখন আমি ScrollViewস্ক্রোলিং শেষ করি তখন আমি যে কোনও কোড চাইব । অ্যান্ড্রয়েডের সাথে কি এমন জিনিস আছে? অথবা এটি করার আরও ভাল উপায় বের করার জন্য আমি কিছু কোড দেখতে পারি?

আমি অ্যান্ড্রয়েড ডক্স সন্ধান করেছি এবং এর মতো কিছু খুঁজে পাইনি।

উত্তর:


102

আপনার বর্ণিত ফাংশনটি আমি সম্প্রতি বাস্তবায়ন করতে হয়েছিল। আমি কি করেছিলাম একটি runnable চেক আউট যদি ScrollView getScrollY দ্বারা ফিরে মান তুলনা করে স্ক্রলিং বন্ধ করে আছে ছিল () যখন onTouchEvent প্রথমে একটি সময় পরিবর্তনশীল দ্বারা সংজ্ঞায়িত পর ফিরে মান সূত্রপাত হয় newCheck

নীচের কোডটি দেখুন (কাজের সমাধান):

public class MyScrollView extends ScrollView{

private Runnable scrollerTask;
private int initialPosition;

private int newCheck = 100;
private static final String TAG = "MyScrollView";

public interface OnScrollStoppedListener{
    void onScrollStopped();
}

private OnScrollStoppedListener onScrollStoppedListener;

public MyScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);

    scrollerTask = new Runnable() {

        public void run() {

            int newPosition = getScrollY();
            if(initialPosition - newPosition == 0){//has stopped

                if(onScrollStoppedListener!=null){

                    onScrollStoppedListener.onScrollStopped();
                }
            }else{
                initialPosition = getScrollY();
                MyScrollView.this.postDelayed(scrollerTask, newCheck);
            }
        }
    };
}

public void setOnScrollStoppedListener(MyScrollView.OnScrollStoppedListener listener){
    onScrollStoppedListener = listener;
}

public void startScrollerTask(){

    initialPosition = getScrollY();
    MyScrollView.this.postDelayed(scrollerTask, newCheck);
}

}

তারপরে আমার আছে:

scroll.setOnTouchListener(new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {

            if (event.getAction() == MotionEvent.ACTION_UP) {

                scroll.startScrollerTask();
            }

            return false;
        }
});
scroll.setOnScrollStoppedListener(new OnScrollStoppedListener() {

        public void onScrollStopped() {

            Log.i(TAG, "stopped");

        }
});

বিটিডাব্লু আমি আমার অ্যাপ্লিকেশনে এটি করতে অন্যান্য জবাব থেকে কয়েকটি ধারণা ব্যবহার করেছি। আশাকরি এটা সাহায্য করবে. কোন প্রশ্ন থাকলে বিনা দ্বিধায় জিজ্ঞাসা করুন। চিয়ার্স


11
ধন্যবাদ, যুগে যুগে এরকম কিছু খুঁজছেন। পরিবর্তে হরিজন্টস্ক্রোলভিউয়ের জন্য ব্যবহৃত হয়, যা (স্পষ্টতই) পাশাপাশি কাজ করে। শুধুমাত্র getScrolY () getScrolX () দ্বারা প্রতিস্থাপন করতে হবে
Schnodahipfe

4
এখানে সব চেষ্টা করেছেন। এটি কেবলমাত্র কাজ করে।
মাইক 6679

23

এখানে আইএমএইচও-র আরও একটি ফিক্স রয়েছে, স্ক্রোলভিউতে অনএন্ডস্ক্রোল ইভেন্ট বাগটি অনুপস্থিত।

এটি স্বচ্ছ উত্তর দিয়ে অনুপ্রাণিত । কেবল এই প্রকল্পটিকে আপনার প্রকল্পে ফেলে দিন (নিজের সাথে মেলে প্যাকেজ পরিবর্তন করুন) এবং নীচের এক্সএমএল ব্যবহার করুন

package com.thecrag.components.ui;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;

public class ResponsiveScrollView extends ScrollView {

    public interface OnEndScrollListener {
        public void onEndScroll();
    }

    private boolean mIsFling;
    private OnEndScrollListener mOnEndScrollListener;

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

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

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

    @Override
    public void fling(int velocityY) {
        super.fling(velocityY);
        mIsFling = true;
    }

    @Override
    protected void onScrollChanged(int x, int y, int oldX, int oldY) {
        super.onScrollChanged(x, y, oldX, oldY);
        if (mIsFling) {
            if (Math.abs(y - oldY) < 2 || y >= getMeasuredHeight() || y == 0) {
                if (mOnEndScrollListener != null) {
                    mOnEndScrollListener.onEndScroll();
                }
                mIsFling = false;
            }
        }
    }

    public OnEndScrollListener getOnEndScrollListener() {
        return mOnEndScrollListener;
    }

    public void setOnEndScrollListener(OnEndScrollListener mOnEndScrollListener) {
        this.mOnEndScrollListener = mOnEndScrollListener;
    }

}

আবার আপনার প্রকল্পের সাথে মেলে প্যাকেজের নাম পরিবর্তন করা

<com.thecrag.components.ui.ResponsiveScrollView
        android:id="@+id/welcome_scroller"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/welcome_scroll_command_help_container"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/welcome_header_text_thecrag"
        android:layout_margin="6dp">
    ....
</com.thecrag.components.ui.ResponsiveScrollView>

4
+1 দুর্দান্ত, সহজ উত্তর। আমি পার্থক্য মান পরিবর্তন 2করতে 0.5fমূল প্রতিফলিত ScrollViewএর MAX_SCROLL_FACTORমান।
ফিল

4
এই বাস্তবায়নটি দুর্দান্ত তবে এটি ব্যর্থ হয়েছে যখন শুরুতে স্ক্রোল দৃশ্যটি পূরণ করা হয় না। এখানে একটি কার্যনির্বাহী (একটি অনুভূমিক স্ক্রোল দেখার জন্য, সুতরাং উল্লম্ব চিত্রটি পেতে সমস্ত x কে y দ্বারা প্রতিস্থাপন করুন): @ ওভাররাইড সুরক্ষিত শূন্যর onScrolChanged (int x, int y, int oldX, int oldY) {super.onScrolChanged (x, y , ওল্ডএক্স, ওল্ডওয়াই); যদি (ম্যাথ.অ্যাবস (এক্স - ওলএলএক্স) <এসসিআরএলএল_ফিনআইএসএইচএইচআরএইচএইচডিএল & এক্স! = লাস্টস্টপেক্স || x> = getMeasuredWidth () || x == 0) {লাস্টস্টপএক্স = এক্স; যদি (mOnEndScrolListener! = নাল) {mOnEndScrolListener.onScrolEded (); }}}
Snicolas

এটি সবসময় কাজ করে না। এমুলেটর হিসাবে, সর্বজনীন শূন্য ঝাঁকুনি (int বেগ) সবসময় বলা হয় না। স্ক্রোল শেষ প্রান্তিক সময় কখনও কখনও 20 px এর বেশি হয়।
অ্যান্ড্রু ফেং

9

আমি (অনুভূমিক) স্ক্রোলভিউ সাবক্লাস করেছি এবং এরকম কিছু করেছি:

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
    if (Math.abs(x - oldX) > SlowDownThreshold) {  
        currentlyScrolling = true;
    } else {
        currentlyScrolling = false;
        if (!currentlyTouching) {
            //scrolling stopped...handle here
        }
    }
    super.onScrollChanged(x, y, oldX, oldY);
}

আমি স্লোডাউনট্রেসোল্ডের জন্য 1 এর মান ব্যবহার করেছি কারণ এটি সর্বদা শেষ অনস্ক্রোলচেনড ইভেন্টের পার্থক্য বলে মনে হয়।

ধীরে ধীরে টেনে আনার সময় এই আচরণটি সঠিকভাবে করার জন্য, আমাকে এটি করতে হয়েছিল:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            currentlyTouching = true;
    }
    return super.onInterceptTouchEvent(event);
}

@Override
public boolean onTouch(View view, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            currentlyTouching = false;
            if (!currentlyScrolling) {
                //I handle the release from a drag here
                return true;
            }
    }
    return false;
}

চমৎকার উত্তর. শুধুমাত্র একটি সংযোজন। অনিটারসেপ্ট টাচ এভেনট () এ আপনি মোশনইভেন্টও করেছেন CTIONঅ্যাকশন_আপ এবং মোশনএভেন্ট CTION অ্যাকশন_সিএনএসএল অন্যথায় বর্তমানে ক্লিকটিতে আপনি অন্য কোনও ক্রিয়াকলাপটি খোলার ক্ষেত্রে পাঠদানটি সত্যই থাকবে।
সিনিচনি বান্দেরা

আরও একটি সমাধান: অনস্ক্রোলচেন্জড () এ আপনি ধীরগতি এখনও না হলেও এমনকি আপনার স্ক্রোলের সমাপ্তিও পরীক্ষা করতে হবে this এর মতো: বুলিয়ান শেষ = (ওল্ডেক্স> এক্স)? (x <= 0): (x> = getMaxScrolAmount ()); যদি (ম্যাথ.অবস (এক্স - ওলেক্স)> 1 &&! শেষ) {স্ক্রোল শুরু; } অন্য {স্ক্রোল শেষ}
সিনিচনি বানেরা

এটি কিছু ডিভাইস, অর্থাৎ জিএস 3 এ কাজ করে না। আমার জিএস 3-তে, স্ক্রোলের মাঝামাঝি সময়ে y এবং পুরাতন y এর মধ্যে পার্থক্য 1 হতে পারে। যদিও এটি আমার নেক্সাস 4 এ পুরোপুরি কাজ করে। আমি নিশ্চিত না কেন।
ব্রায়ান

স্যামসাং গ্যালাক্সি নোট 2 এবং আসুস মেমো প্যাড 7 তেও কাজ করছে না। আমি এই ডিভাইসগুলিতে স্ক্রোলের মাঝখানে 1 এর বৃদ্ধিও দেখতে পাচ্ছি।
অলিভার হাউসলার

7

আমার দৃষ্টিভঙ্গি স্ক্রোলিংয়ের স্থিতি স্থির করে টাইমস্ট্যাম্পের মাধ্যমে প্রতিবার onscrolChanged () বলা হয় changed কখন স্ক্রোলিং শুরু এবং শেষ তা নির্ধারণ করা খুব সহজ। সংবেদনশীলতা ঠিক করতে আপনি প্রান্তিক পরিবর্তন (আমি 100 মিমি) ব্যবহার করতে পারেন।

public class CustomScrollView extends ScrollView {
    private long lastScrollUpdate = -1;

    private class ScrollStateHandler implements Runnable {

        @Override
        public void run() {
            long currentTime = System.currentTimeMillis();
            if ((currentTime - lastScrollUpdate) > 100) {
                lastScrollUpdate = -1;
                onScrollEnd();
            } else {
                postDelayed(this, 100);
            }
        }
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (lastScrollUpdate == -1) {
            onScrollStart();
            postDelayed(new ScrollStateHandler(), 100);
        }

        lastScrollUpdate = System.currentTimeMillis();
    }

    private void onScrollStart() {
        // do something
    }

    private void onScrollEnd() {
        // do something
    }

}

দুর্দান্ত সমাধান। অনুমিত হিসাবে কাজ করে।
অলিভার হাউসলার

আপনার কোডের জন্য ধন্যবাদ। কীভাবে আপনার কোড থেকে স্ক্রোল শুরু শ্রোতার পদ্ধতি সনাক্ত করবেন। দয়া করে আমার প্রশ্নের চেহারা stackoverflow.com/questions/27864700/...
MAMurali

7

উপরের উত্তরগুলি দ্বারা প্রাকৃতিকভাবে অনুপ্রাণিত, আমার মতে বেশ সহজ এবং পরিষ্কারভাবে এখানে আরও একটি সমাধান রয়েছে। মূলত একবার ব্যবহারকারীর অঙ্গভঙ্গিটি পরীক্ষা করে দেখুন getScrolY () এখনও সংক্ষিপ্ত বিলম্বের পরে (এখানে 50 মিমি) পরিবর্তিত হচ্ছে।

public class ScrollViewWithOnStopListener extends ScrollView {

    OnScrollStopListener listener;

    public interface OnScrollStopListener {
        void onScrollStopped(int y);
    }

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

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

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:
                checkIfScrollStopped();
        }

        return super.onTouchEvent(ev);
    }

    int initialY = 0;

    private void checkIfScrollStopped() {
        initialY = getScrollY();
        this.postDelayed(new Runnable() {
            @Override
            public void run() {
                int updatedY = getScrollY();
                if (updatedY == initialY) {
                    //we've stopped
                    if (listener != null) {
                        listener.onScrollStopped(getScrollY());
                    }
                } else {
                    initialY = updatedY;
                    checkIfScrollStopped();
                }
            }
        }, 50);
    }

    public void setOnScrollStoppedListener(OnScrollStopListener yListener) {
        listener = yListener;
    }
}

5

এই প্রশ্নের জন্য আমার পদ্ধতিরটি হল নিম্নলিখিত 2 "ইভেন্টগুলি" যাচাই করার জন্য একটি টাইমার ব্যবহার করা।

1) oncrolChanged () কল করা বন্ধ হয়ে গেছে

2) ব্যবহারকারীর আঙুলটি স্ক্রোলভিউ থেকে উত্তোলন করা হয়

public class CustomScrollView extends HorizontalScrollView {

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

Timer ntimer = new Timer();
MotionEvent event;

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) 
{
    checkAgain();
    super.onScrollChanged(l, t, oldl, oldt);
}

public void checkAgain(){
    try{
        ntimer.cancel();
        ntimer.purge();
    }
    catch(Exception e){}
    ntimer = new Timer();
    ntimer.schedule(new TimerTask() {

        @Override
        public void run() {

            if(event.getAction() == MotionEvent.ACTION_UP){
                // ScrollView Stopped Scrolling and Finger is not on the ScrollView
            }
            else{
                // ScrollView Stopped Scrolling But Finger is still on the ScrollView
                checkAgain();
            }
        }
    },100);

}

@Override
public boolean onTouchEvent(MotionEvent event) {
    this.event = event; 
    return super.onTouchEvent(event);
    }
}

3

আপনি বর্ণিত মত একটি সাধারণ ক্ষেত্রে, আপনি সম্ভবত আপনার কাস্টম স্ক্রোল ভিউতে ওভাররাইডিং ফ্লিং পদ্ধতিটি দিয়ে পালিয়ে যেতে পারেন। ঝাঁকুনির পদ্ধতিটি প্রতিবার পর্দা থেকে আঙুল উত্থাপিত করে "হ্রাস" সম্পাদনের জন্য ডেকে আনা হয়।

সুতরাং আপনার যা করা উচিত তা হ'ল:

  1. সাবক্লাস স্ক্রোলভিউ।

    public class MyScrollView extends ScrollView { 
    
        private Scroller scroller;  
        private Runnable scrollerTask; 
    
        //...
    
        public MyScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            scroller = new Scroller(getContext()); //or OverScroller for 3.0+
            scrollerTask = new Runnable() {
                @Override
                public void run() {
                    scroller.computeScrollOffset();
                    scrollTo(0, scroller.getCurrY());
    
                    if (!scroller.isFinished()) {
                        MyScrollView.this.post(this);
                    } else {
                        //deceleration ends here, do your code
                    }
                }
            };
            //...
        }
    }
    
  2. সাবক্লাস ফিটিং পদ্ধতি এবং সুপারক্লাস বাস্তবায়ন কল করবেন না।

    @Override  
    public void fling(int velocityY) {  
        scroller.fling(getScrollX(), getScrollY(), 0, velocityY, 0, 0, 0, container.getHeight());
        post(scrollerTask);  
    
        //add any extra functions you need from android source code:
        //show scroll bars
        //change focus
        //etc.
    }
    
  3. ব্যবহারকারী তার আঙুলটি উত্থাপনের আগে স্ক্রোলিং বন্ধ করে দিলে (গতিবেগ == 0) ট্রিপিং ট্রিগার হবে না। আপনি যদি এই ধরণের ইভেন্টগুলিকে পাশাপাশি আটকাতে চান তবে টুচেন্টে ওভাররাইড করুন।

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean eventConsumed = super.onTouchEvent(ev);
        if (eventConsumed && ev.getAction() == MotionEvent.ACTION_UP) {
            if (scroller.isFinished()) {
                //do your code
            }
        }
        return eventConsumed;
    }
    

দ্রষ্টব্য যদিও এটি কাজ করে, ওভাররাইডিং ফ্লিং পদ্ধতিটি একটি খারাপ ধারণা হতে পারে। এটি সর্বজনীন, তবে এটি কেবল সাবক্লাসিংয়ের জন্য ডিজাইন করা হয়েছে। এখনই এটি 3 টি কাজ করে - এটি ব্যক্তিগত এমএসক্রোলারের জন্য ঝাঁকুনির সূচনা করে, সম্ভাব্য ফোকাস পরিবর্তনগুলি পরিচালনা করে এবং স্ক্রোল বারগুলি দেখায়। এটি ভবিষ্যতে অ্যান্ড্রয়েড প্রকাশে পরিবর্তিত হতে পারে। উদাহরণস্বরূপ, বেসরকারী এমস্ক্রোলার উদাহরণটি তার শ্রেণিটিকে স্ক্রোলার থেকে ২.৩ এবং 3.0 এর মধ্যে ওভারশুটস্ক্রোলারে পরিবর্তন করেছে। এই সমস্ত ছোট পার্থক্য আপনাকে মনে রাখতে হবে। যাই হোক না কেন, ভবিষ্যতে অপ্রত্যাশিত পরিণতির জন্য প্রস্তুত থাকুন।


দ্বিতীয় ধাপে কন্টেইনার.ইটহাইট () কী (2)?
মিতুল ভারমোড়া

4
ধারক হ'ল স্ক্রোলভিউয়ের ভিতরে থাকা দৃশ্য। যেহেতু স্ক্রোলভিউতে কেবলমাত্র 1 টি শিশু থাকতে পারে, তাই আপনি getChildAt (0) দিয়ে ধারক প্রতিস্থাপন করতে পারেন।
আলেক্সি

3

আমার সমাধান লিন ইউ চেংয়ের দুর্দান্ত সমাধানের একটি প্রকরণ এবং যখন স্ক্রোলিং শুরু হয়েছে এবং বন্ধ হয়েছে তখন তা সনাক্ত করে।

পদক্ষেপ 1. একটি অনুভূমিকস্ক্রোলভিউ এবং অনস্ক্রোলচেনডলাইস্টেনার সংজ্ঞা দিন:

CustomHorizontalScrollView scrollView = (CustomHorizontalScrollView) findViewById(R.id.horizontalScrollView);

horizontalScrollListener = new CustomHorizontalScrollView.OnScrollChangedListener() {
    @Override
    public void onScrollStart() {
        // Scrolling has started. Insert your code here...
    }

    @Override
    public void onScrollEnd() {
         // Scrolling has stopped. Insert your code here...
    }
};

scrollView.setOnScrollChangedListener(horizontalScrollListener);

পদক্ষেপ 2. কাস্টমহোরাইজেন্টালস্ক্রোলভিউ ক্লাস যুক্ত করুন:

public class CustomHorizontalScrollView extends HorizontalScrollView {
    public interface OnScrollChangedListener {
        // Developer must implement these methods.
        void onScrollStart();
        void onScrollEnd();
    }

    private long lastScrollUpdate = -1;
    private int scrollTaskInterval = 100;
    private Runnable mScrollingRunnable;
    public OnScrollChangedListener mOnScrollListener;

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

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

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

    private void init(Context context) {
        // Check for scrolling every scrollTaskInterval milliseconds
        mScrollingRunnable = new Runnable() {
            public void run() {
                if ((System.currentTimeMillis() - lastScrollUpdate) > scrollTaskInterval) {
                    // Scrolling has stopped.
                    lastScrollUpdate = -1;
                    //CustomHorizontalScrollView.this.onScrollEnd();
                    mOnScrollListener.onScrollEnd();
                } else {
                    // Still scrolling - Check again in scrollTaskInterval milliseconds...
                    postDelayed(this, scrollTaskInterval);
                }
            }
        };
    }

    public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) {
        this.mOnScrollListener = onScrollChangedListener;
    }

    public void setScrollTaskInterval(int scrollTaskInterval) {
        this.scrollTaskInterval = scrollTaskInterval;
    }

    //void onScrollStart() {
    //    System.out.println("Scroll started...");
    //}

    //void onScrollEnd() {
    //    System.out.println("Scroll ended...");
    //}

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mOnScrollListener != null) {
            if (lastScrollUpdate == -1) {
                //CustomHorizontalScrollView.this.onScrollStart();
                mOnScrollListener.onScrollStart();
                postDelayed(mScrollingRunnable, scrollTaskInterval);
            }

            lastScrollUpdate = System.currentTimeMillis();
        }
    }
}

2

স্ট্যাকওভারফ্লোতে এই প্রশ্নটি একবার দেখার চেষ্টা করুন - এটি আপনার প্রশ্নের মতো নয়, তবে আপনি কী এর স্ক্রোল ইভেন্টটি পরিচালনা করতে পারবেন সে সম্পর্কে ধারণা দেয় ScrollView

মূলত আপনাকে CustomScrollViewপ্রসারিত ScrollViewএবং ওভাররাইড করে নিজের তৈরি করতে হবে onScrollChanged(int x, int y, int oldx, int oldy)। তারপর আপনি মান পরিবর্তে আপনার লেআউট ফাইলের মধ্যে এই রেফারেন্স প্রয়োজন ScrollViewমত com.mypackage.CustomScrollView


এই অনস্ক্রোলচেন্জড () আসলে আমি এই মুহুর্তে ব্যবহার করছি। ধন্যবাদ যদিও.
ব্যবহারকারী 1053691

2

এখানে কিছু দুর্দান্ত উত্তর রয়েছে তবে আমার কোড সনাক্ত করতে পারে যখন স্ক্রোলভিউ ক্লাস না বাড়িয়ে স্ক্রোলিং বন্ধ হয়ে যায়। প্রতিটি দর্শন ইভেন্ট getViewTreeObserver () কল করতে পারে। ViewTreeObserver এর এই ইভেন্টটি ধরে রাখলে আপনি addOnScrollChangedListener () ফাংশনটি ব্যবহার করে একটি OnScrollChangedListener যুক্ত করতে পারেন।

নিম্নলিখিত ঘোষণা:

private ScrollView scrollListener;
private volatile long milesec;

private Handler scrollStopDetector;
private Thread scrollcalled = new Thread() {

    @Override
    public void run() { 
        if (System.currentTimeMillis() - milesec > 200) {
            //scroll stopped - put your code here
        }
    }
}; 

এবং আপনার অনক্রিটে (বা অন্য কোনও জায়গায়) যুক্ত করুন:

    scrollListener = (ScrollView) findViewById(R.id.scroll);

    scrollListener.getViewTreeObserver().addOnScrollChangedListener(new OnScrollChangedListener() {

        @Override
        public void onScrollChanged() {
            milesec = System.currentTimeMillis();
            scrollStopDetector.postDelayed(scrollcalled, 200);
        }
    });

আপনি এই চেকগুলির মধ্যে আরও বেশি বা ধীর সময় নিতে চাইবেন তবে এই তালিকাটি যখন স্ক্রল করা হয় তখন সত্যিই দ্রুত বলা হয় যাতে এটি খুব দ্রুত কাজ করবে।


আমি এই ক্ষেত্রে চেষ্টা করি নি, তবে আমার অভিজ্ঞতা থেকে আমি অনুমান করব যে অনস্ক্রোলচ্যাঞ্জড থেকে পোস্টডিলিয়েডের পুনরাবৃত্ত এবং পুনঃসংযোগ কল মেমরি ফাঁসের কারণ ঘটবে।
অলিভার হাউসলার

2

এখানে আমার সমাধানটিতে স্ক্রোল ট্র্যাকিং এবং স্ক্রোল সমাপ্তি অন্তর্ভুক্ত রয়েছে:

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;
    }

}

2

আমি মনে করি এটি অতীতেও উঠে এসেছে। আফাইক, আপনি সহজেই এটি সনাক্ত করতে পারবেন না । আমার পরামর্শটি হ'ল আপনি একবার নজর দিন ScrollView.java(আমরা এন্ড্রয়েড জমিতে কীভাবে কাজ করি :)) এবং আপনি যে কার্যকারিতাটি সন্ধান করছেন তা সরবরাহ করতে আপনি কীভাবে শ্রেণিটি বাড়িয়ে দিতে পারেন তা নির্ধারণ করুন। এটিই আমি প্রথমে চেষ্টা করব:

 @Override
 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
     if (mScroller.isFinished()) {
         // do something, for example call a listener
     }
 }

চমৎকার আমি আইফিনিশ পদ্ধতিটি খেয়াল করিনি!
জর্দি কস্কোল্লা

4
ধন্যবাদ আমি এই ইসফিনিশড () পদ্ধতিতে কীভাবে অ্যাক্সেস করব? আমি স্ক্রোলভিউ.জভা ফাইলটি দেখেছি এবং এমএসক্রোলারটি ব্যক্তিগত এবং আমি এতে অ্যাক্সেস পাওয়ার কোনও উপায় বলতে পারি না।
ব্যবহারকারী 1053691

হুঁ, সত্যিই। আমি যথেষ্ট কাছাকাছি না তাকান। সে কারণেই আমি বলেছিলাম যে আমি প্রথমে চেষ্টা করব :) :) আপনি অন্য কিছু করতে পারে, ট্র্যাকের আহ্বান মত onScrollChanged, scrollTo, বা অন্য কোন স্ক্রোল সম্পর্কিত পদ্ধতি। বিকল্পভাবে, আপনি কেবল পুরো ScrollViewকোডটি অনুলিপি করতে পারেন এবং সেই ক্ষেত্রটি তৈরি করতে পারেন protected। যদিও আমি এটি সুপারিশ করব না।
ফেলিক্স

4
প্রতিবিম্ব মাধ্যমে এমএসক্রোলার অ্যাক্সেস করা হয়েছে। খুব বেশি কাজ করে না, আইসফিনিশড () প্রতিবার স্ক্রোলভিউটি আপনার আঙুলের অবস্থানে পৌঁছায় তাত্পর্যপূর্ণ হয় যা প্রায় অবিচ্ছিন্ন S যখন উভয় ব্যবহারকারী তার আঙুল ছেড়ে দেয় এবং স্ক্রোলার স্ক্রোলিং বন্ধ করে দেয় তখন স্ক্রোল স্টপ ইভেন্টটি চালিত হওয়া উচিত।
amik

20
এই উত্তরটি সত্যিই আশাব্যঞ্জক বলে মনে হচ্ছে তবে যেহেতু এটি মৃতু্যর ধরণের শেষ হয়েছে, সম্ভবত এটি অপসারণ করা উচিত?
spaaarky21

2

এটি একটি পুরানো থ্রেড তবে আমি একটি সংক্ষিপ্ত সমাধান যুক্ত করতে চাই যার সাথে আমি এলাম:

 buttonsScrollView.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->

            handler.removeCallbacksAndMessages(null)

            handler.postDelayed({
                  //YOUR CODE TO BE EXECUTED HERE
                },1000)
        }

স্বাভাবিকভাবেই 1000 মিলি সেকেন্ডের বিলম্ব রয়েছে। আপনার প্রয়োজন হলে এটি সামঞ্জস্য করুন।


1

জিরোগের উত্তরে আমি কিছু উন্নতি করেছি। মূলত অতিরিক্ত টাস্ক কল বাতিল করা এবং গোটা বিষয়টিকে একটি ব্যক্তিগত অন টচলিস্টনার হিসাবে বাস্তবায়ন করা, যাতে সমস্ত স্ক্রোল সনাক্তকরণ কোড এক জায়গায় থাকবে।

আপনার নিজের স্ক্রোলভিউ বাস্তবায়নে নিম্নলিখিত কোডটি আটকে দিন:

private class ScrollFinishHandler implements OnTouchListener
{
        private static final int SCROLL_TASK_INTERVAL = 100;

        private Runnable    mScrollerTask;
        private int         mInitialPosition = 0;

        public ScrollFinishHandler()
        {
            mScrollerTask = new Runnable() {

                public void run() {

                    int newPosition = getScrollY();
                    if(mInitialPosition - newPosition == 0)
                    {//has stopped

                       onScrollStopped(); // Implement this on your main ScrollView class
                    }else{
                        mInitialPosition = getScrollY();
                        ExpandingLinearLayout.this.postDelayed(mScrollerTask, SCROLL_TASK_INTERVAL);
                    }
                }
            };
        }

        @Override
        public boolean onTouch(View v, MotionEvent event) 
        {
            if (event.getAction() == MotionEvent.ACTION_UP) 
            {

                startScrollerTask();
            }
            else
            {
                stopScrollerTask();
            }

            return false;
        }

}

এবং তারপরে আপনার স্ক্রোলভিউ বাস্তবায়নে:

setOnTouchListener( new ScrollFinishHandler() );

-1
        this.getListView().setOnScrollListener(new OnScrollListener(){
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {}

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
                     if( firstVisibleItem + visibleItemCount >= totalItemCount ) 
                              // Last item is shown...

            }

স্নিপেট সাহায্য আশা করি :)


দুর্ভাগ্যক্রমে আমি কোনও তালিকা ভিউ নয়, একটি স্ক্রোলভিউ ব্যবহার করছি। ধন্যবাদ যদিও.
ব্যবহারকারী 1053691

4
হ্যালো? স্ক্রোলভিউ তালিকাভুক্ত নয়।
কেভিন পার্কার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.