অ্যান্ড্রয়েড: স্ক্রোলভিউর ভিতরে কোনও ভিউ দৃশ্যমান কিনা তা কীভাবে পরীক্ষা করবেন?


168

আমার একটি আছে ScrollViewযা একটি সিরিজ ধারণ করে Views। আমি বর্তমানে কোনও দৃশ্য দৃশ্যমান কিনা তা নির্ধারণ করতে সক্ষম হতে চাই (যদি এর কোনও অংশ বর্তমানে দ্বারা প্রদর্শিত হয় ScrollView)। আমি নীচের কোডটি এটি করার আশা করব, আশ্চর্যরকমভাবে এটি হয় না:

Rect bounds = new Rect();
view.getDrawingRect(bounds);

Rect scrollBounds = new Rect(scroll.getScrollX(), scroll.getScrollY(), 
        scroll.getScrollX() + scroll.getWidth(), scroll.getScrollY() + scroll.getHeight());

if(Rect.intersects(scrollBounds, bounds))
{
    //is  visible
}

আপনি কীভাবে এটি কাজ করতে পেলেন তা জানতে আগ্রহী। আমি একই জিনিসটি করার চেষ্টা করছি তবে একটি স্ক্রোলভিউ কেবল ১ জন সরাসরি শিশুকে হোস্ট করতে পারে। আপনার "সিরিজের দর্শনগুলি" কী স্ক্রোলভিউয়ের অভ্যন্তরে অন্য বিন্যাসে আবৃত রয়েছে? এটি আমার বিভক্ত করা হয় তবে আমি যখন তা করি তবে এখানে দেওয়া উত্তরগুলির কোনওটাই আমার পক্ষে কাজ করে না।
রুস্টার 242

1
হ্যাঁ, আমার সিরিজের দর্শনগুলি লিনিয়ারলআউটের ভিতরে, যা স্ক্রোলভিউয়ের 1 সন্তানের। কিবার্টিকাসের উত্তর আমার পক্ষে কাজ করেছিল।
ab11

উত্তর:


65

View#getHitRectপরিবর্তে ব্যবহার করুনView#getDrawingRectআপনি যা পরীক্ষা করছেন তা দেখার । আপনি ব্যবহার করতে পারেন View#getDrawingRectউপর ScrollViewস্পষ্টভাবে গণক পরিবর্তে।

থেকে কোড View#getDrawingRect:

 public void getDrawingRect(Rect outRect) {
        outRect.left = mScrollX;
        outRect.top = mScrollY;
        outRect.right = mScrollX + (mRight - mLeft);
        outRect.bottom = mScrollY + (mBottom - mTop);
 }

থেকে কোড View#getHitRect:

public void getHitRect(Rect outRect) {
        outRect.set(mLeft, mTop, mRight, mBottom);
}

35
আমি এই পদ্ধতিগুলি কোথায় কল করব?
টুটো

3
@ কিবার্টিকাস কীভাবে পদ্ধতিগুলি কল করবেন? আমি এটি ব্যবহার করছি এবং এটি সর্বদা মিথ্যা প্রত্যাবর্তন করে। দয়া করে আমাকে জানান
KK_07k11A0585

2
ঠিক কোথায় এই পদ্ধতিগুলি কল?
জেমাইটিস

193

এইটা কাজ করে:

Rect scrollBounds = new Rect();
scrollView.getHitRect(scrollBounds);
if (imageView.getLocalVisibleRect(scrollBounds)) {
    // Any portion of the imageView, even a single pixel, is within the visible window
} else {
    // NONE of the imageView is within the visible window
}

1
পুরোপুরি কাজ করে। এটি পরিষ্কার করার জন্য: দৃশ্যটি সম্পূর্ণ বা আংশিকভাবে দৃশ্যমান হলে সত্য প্রত্যাবর্তন হয়; মিথ্যা মানে ভিউটি সম্পূর্ণ দৃশ্যমান নয়।
কিওয়ার্টজগুয়ে

1
[+ 1] আমি পেতে এই কোড ব্যবহার GridView/ ListView/ GridViewWithHeaderসঙ্গে কাজ SwipeRefreshLayout
কার্তিক

কেউ দয়া করে ব্যাখ্যা করতে পারেন কেন এটি কাজ করে? getHitRectঅভিভাবক স্থানাঙ্কগুলিতে getLocalVisibleRectএকটি রেকট প্রদান করে, তবে স্ক্রোলভিউয়ের স্থানীয় স্থানাঙ্কগুলিতে একটি রেকট ফেরত দেয়, তাই না?
পিন করুন

3
এটি ওভারল্যাপগুলি কভার করে না, চাইল্ড ভিউ যদি অন্য কোনও শিশু উপাদান দ্বারা আবৃত হয় তবে এটি সত্য হয়ে যাবে
প্রদীপ

1
হ্যাঁ, আমাদের রেক্টের একটি দৃষ্টান্ত প্রয়োজন B তবে হিটআরেক্ট পাওয়া দরকার is যদি আমি একটি আয়তক্ষেত্র ব্যবহার কোন ভিন্ন (0,0-0,0) স্থায়ী করা হবে আমরা দেখতে পারেন getLocalVisibleRect কল getGlobalVisibleRect.And আয়তক্ষেত্র এখানে r.set সেট করা হয় (0, 0, প্রস্থ, উচ্চতা); @ BillMote।
chefish

56

আপনি সনাক্ত করতে যে দৃশ্য চান সম্পূর্ণরূপে দৃশ্যমান:

private boolean isViewVisible(View view) {
    Rect scrollBounds = new Rect();
    mScrollView.getDrawingRect(scrollBounds);

    float top = view.getY();
    float bottom = top + view.getHeight();

    if (scrollBounds.top < top && scrollBounds.bottom > bottom) {
        return true;
    } else {
        return false;
    }
}

6
এটি সঠিক উত্তর =) আমার ক্ষেত্রে আমি এটির মতো পরিবর্তন করেছি: স্ক্রোলবাউন্ডস.টপ <= শীর্ষে && স্ক্রোলবাউন্ডস = নীচে
হেলটন ইসাক

2
+1 হেলটন যদি আপনার ভিউটি যদি আপনার স্ক্রোল দর্শনের জন্য উপরে বা নীচের দিকে ঠেলা যায় তবে আপনার যথাক্রমে <= বা> = প্রয়োজন হবে
জো মাহের

আপনি কি সত্যিই এটি পরীক্ষা করেছেন? এটি সর্বদা সর্বাধিক সরল বিন্যাসে স্ক্রোলভিউ এবং টেক্সটভিউতে ছোট হিসাবে প্রত্যাবর্তন করে।
ফরিদ

1
GetHitRect () এবং getDrawingRect () এর মধ্যে কী পার্থক্য রয়েছে? দয়া করে গাইড করুন
ভিভিবি

2
এই কোডটি কেবলমাত্র যদি স্ক্রোলভিউ ধারকটির মূলটিতে ভিউটি যুক্ত করা হয় কেবল তখনই কাজ করে। আপনি যদি কোনও শিশু দর্শন ইত্যাদিতে কোনও শিশু দৃষ্টিভঙ্গি পরিচালনা করতে চান তবে ফান ভ্যান
লিনহের উত্তরটি

12

আমার সমাধানটি NestedScrollViewস্ক্রোল উপাদানটি ব্যবহার করছে :

    final Rect scrollBounds = new Rect();
    scroller.getHitRect(scrollBounds);

    scroller.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
        @Override
        public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {

            if (myBtn1 != null) {

                if (myBtn1.getLocalVisibleRect(scrollBounds)) {
                    if (!myBtn1.getLocalVisibleRect(scrollBounds)
                            || scrollBounds.height() < myBtn1.getHeight()) {
                        Log.i(TAG, "BTN APPEAR PARCIALY");
                    } else {
                        Log.i(TAG, "BTN APPEAR FULLY!!!");
                    }
                } else {
                    Log.i(TAG, "No");
                }
            }

        }
    });
}

API প্রয়োজন 23+
SolidSnake

@ সলিডসনেকে, আপনার আলাদা শ্রেণি আমদানির দরকার নেই, এটি দুর্দান্ত কাজ করে
পার্থ আঞ্জারিয়া

10

GetLocalVisibleRect ব্যবহার করে বিল মোটের উত্তরে কিছুটা প্রসারিত করতে, আপনি দেখতে চান যে দৃশ্যটি কেবলমাত্র আংশিকভাবে দৃশ্যমান রয়েছে:

Rect scrollBounds = new Rect();
scrollView.getHitRect(scrollBounds);
if (!imageView.getLocalVisibleRect(scrollBounds)
    || scrollBounds.height() < imageView.getHeight()) {
    // imageView is not within or only partially within the visible window
} else {
    // imageView is completely visible
}

6
এটি কাজ করে না .. এমনকি আংশিক দৃশ্যমান দৃশ্যকে সম্পূর্ণ দৃশ্যমান হিসাবে শ্রেণীবদ্ধ করা হয়েছে
আজফার

10

এই এক্সটেনশনটি সম্পূর্ণরূপে দৃশ্যমান দর্শন সনাক্ত করতে সহায়তা করে ।
যদি আপনার View... এর সন্তানের শিশু হয় তবে এটিও কাজ করে ScrollView(যেমন: ScrollView-> LinearLayout-> ContraintLayout-> ... -> YourView)।

fun ScrollView.isViewVisible(view: View): Boolean {
    val scrollBounds = Rect()
    this.getDrawingRect(scrollBounds)
    var top = 0f
    var temp = view
    while (temp !is ScrollView){
        top += (temp).y
        temp = temp.parent as View
    }
    val bottom = top + view.height
    return scrollBounds.top < top && scrollBounds.bottom > bottom
}

বিঃদ্রঃ

1) view.getY()এবং view.getX()x, y মানটি প্রথম প্যারেন্টে ফিরিয়ে দিন ।

2) এখানে লিঙ্কটি কীভাবে getDrawingRectফিরে আসবে সে সম্পর্কে উদাহরণ রয়েছেএখানে চিত্র বর্ণনা লিখুন


আমি একটি সমাধান চেয়েছিলাম যেখানে কীবোর্ডের নীচে ভিউটি লুকানো থাকলে এবং পদ্ধতিটি মিথ্যা ফিরে পাওয়া উচিত। ধন্যবাদ।
রাহুল

8
public static int getVisiblePercent(View v) {
        if (v.isShown()) {
            Rect r = new Rect();
            v.getGlobalVisibleRect(r);
            double sVisible = r.width() * r.height();
            double sTotal = v.getWidth() * v.getHeight();
            return (int) (100 * sVisible / sTotal);
        } else {
            return -1;
        }
    }

2
এটি ab11 যা চেয়েছিল তার চেয়ে আলাদা। আইসশাউন () দৃশ্যটি কেবল পর্দার দৃশ্যমান অঞ্চলে আছে কিনা তা নয়, কেবলমাত্র দৃশ্যমানতার পতাকাটি পরীক্ষা করে।
রোমেন গাই

4
@ রোমাইন গাই কোনও দৃশ্য পর্দা থেকে সরিয়ে স্ক্রোল করার সময় কোডটি কভার করে না t এটি `পাবলিক স্ট্যাটিক ইনট ভিজিবল পার্সেন্ট (ভিউ ভি) হওয়া উচিত {যদি (v.isShown ()) r রেক্ট আর = নতুন রেক্ট (); বুলিয়ান isvisible = v.getGlobalVisibleRect (r); যদি (isVisible) {ডাবল এসভিজিবল = r.width () * r.height (); ডাবল এসটোটাল = v.getWidth () * v.getHeight (); রিটার্ন (ইনট) (100 * এস ভিজিবল / এসটোটাল); } অন্য {রিটার্ন -1; }} অন্য {রিটার্ন -1; }} `
শেফিশ

6

আমি আজ একই সমস্যার মুখোমুখি হয়েছি। গুগলিং এবং অ্যান্ড্রয়েড রেফারেন্স পড়ার সময় আমি এই পোস্টটি এবং তার পরিবর্তে ব্যবহার করে একটি পদ্ধতি পেয়েছি;

public final boolean getLocalVisibleRect (Rect r)

তাদের মধ্যে খুব ভাল কেবল রেট সরবরাহ করে না তবে বুলিয়ানও নির্দেশ করে যে ভিউটি একেবারেই দৃশ্যমান। নেতিবাচক দিক থেকে এই পদ্ধতিটি অননুমোদিত :(


1
আইটেমটি দৃশ্যমানতার (সত্য) সেট করা থাকলে এটি কেবল আপনাকে জানায়। ভিউপোর্টের মধ্যে "দৃশ্যমান" আইটেমটি আসলে দৃশ্যমান কিনা তা আপনাকে জানায় না।
বিল মোটে

GetLocalVisibleRect এর কোডটি আপনার দাবির সমর্থন করে না: `সর্বজনীন চূড়ান্ত বুলিয়ান getLocalVisibleRect (রেক্ট আর) {চূড়ান্ত পয়েন্ট অফসেট = এমএটাচআইএনফো! = নাল? mAttachInfo.mPoint: নতুন পয়েন্ট (); যদি (getGlobalVisibleRect (r, অফসেট)) {r.offset (-offset.x, -offset.y); // স্থানীয় রিটার্ন সত্য করুন; false মিথ্যা প্রত্যাবর্তন; } `
এমবাফর্ড 14

6

আপনার Viewপুরোপুরি কিনা তা আমি সনাক্ত করতে চাই visible, এই পদ্ধতিটি দিয়ে চেষ্টা করুন:

private boolean isViewVisible(View view) {
    Rect scrollBounds = new Rect();
    mScrollView.getDrawingRect(scrollBounds);
    float top = view.getY();
    float bottom = top + view.getHeight();
    if (scrollBounds.top < top && scrollBounds.bottom > bottom) {
        return true; //View is visible.
    } else {
        return false; //View is NOT visible.
    }
}

কঠোরভাবে বলতে গেলে আপনি এর সাথে একটি দৃশ্যের দৃশ্যমানতা পেতে পারেন:

if (myView.getVisibility() == View.VISIBLE) {
    //VISIBLE
} else {
    //INVISIBLE
}

একটি দৃশ্যে দৃশ্যমানতার ধ্রুবক ধ্রুবক মানগুলি হ'ল:

দৃশ্যমান এই দেখুন দৃশ্যমান। সেটভিজিবিলিটি (ইনট) এবং অ্যান্ড্রয়েড: দৃশ্যমানতার সাথে ব্যবহার করুন।

অদৃশ্য এই দৃশ্যটি অদৃশ্য, তবে এটি এখনও লেআউটের উদ্দেশ্যে স্থান নেয়। সেটভিজিবিলিটি (ইনট) এবং অ্যান্ড্রয়েড: দৃশ্যমানতার সাথে ব্যবহার করুন।

যান এই দৃশ্যটি অদৃশ্য, এবং এটি বিন্যাসের উদ্দেশ্যে কোনও স্থান নেয় না। সেটভিজিবিলিটি (ইনট) এবং অ্যান্ড্রয়েড: দৃশ্যমানতার সাথে ব্যবহার করুন।


3
ধীর তালি ওপিটি যা জানতে চেয়েছিল তা হল দৃশ্যের দৃশ্যমানতাটি ধরে নিয়ে দেখুন ভিউ # ভিসিবল, কীভাবে তা কীভাবে জানবেন যে কোনও দৃশ্য কোনও স্ক্রোলভিউয়ের মধ্যে দৃশ্যমান visible
জোওও সউসা

1
আমি সবেমাত্র একটি সাধারণ প্রকল্প পরীক্ষা করেছি। লেআউটটিতে ছোটবেলায় স্ক্রোলভিউ এবং টেক্সটভিউ রয়েছে; টেক্সটভিউ পুরোপুরি দৃশ্যমান হলেও সর্বদা মিথ্যা প্রত্যাবর্তন করে।
ফরিদ

এটি সর্বদা মিথ্যা প্রত্যাবর্তন করে।
রাহুল

3

FocusAwareScrollViewযখন দৃশ্যটি দৃশ্যমান হবে তখন আপনি এটিটি ব্যবহার করতে পারেন :

FocusAwareScrollView focusAwareScrollView = (FocusAwareScrollView) findViewById(R.id.focusAwareScrollView);
    if (focusAwareScrollView != null) {

        ArrayList<View> viewList = new ArrayList<>();
        viewList.add(yourView1);
        viewList.add(yourView2);

        focusAwareScrollView.registerViewSeenCallBack(viewList, new FocusAwareScrollView.OnViewSeenListener() {

            @Override
            public void onViewSeen(View v, int percentageScrolled) {

                if (v == yourView1) {

                    // user have seen view1

                } else if (v == yourView2) {

                    // user have seen view2
                }
            }
        });

    }

এখানে শ্রেণি রয়েছে:

import android.content.Context;
import android.graphics.Rect;
import android.support.v4.widget.NestedScrollView;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

public class FocusAwareScrollView extends NestedScrollView {

    private List<OnScrollViewListener> onScrollViewListeners = new ArrayList<>();

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

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

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

    public interface OnScrollViewListener {
        void onScrollChanged(FocusAwareScrollView v, int l, int t, int oldl, int oldt);
    }

    public interface OnViewSeenListener {
        void onViewSeen(View v, int percentageScrolled);
    }

    public void addOnScrollListener(OnScrollViewListener l) {
        onScrollViewListeners.add(l);
    }

    public void removeOnScrollListener(OnScrollViewListener l) {
        onScrollViewListeners.remove(l);
    }

    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        for (int i = onScrollViewListeners.size() - 1; i >= 0; i--) {
            onScrollViewListeners.get(i).onScrollChanged(this, l, t, oldl, oldt);
        }
        super.onScrollChanged(l, t, oldl, oldt);
    }

    @Override
    public void requestChildFocus(View child, View focused) {
        super.requestChildFocus(child, focused);
    }

    private boolean handleViewSeenEvent(View view, int scrollBoundsBottom, int scrollYOffset,
                                        float minSeenPercentage, OnViewSeenListener onViewSeenListener) {
        int loc[] = new int[2];
        view.getLocationOnScreen(loc);
        int viewBottomPos = loc[1] - scrollYOffset + (int) (minSeenPercentage / 100 * view.getMeasuredHeight());
        if (viewBottomPos <= scrollBoundsBottom) {
            int scrollViewHeight = this.getChildAt(0).getHeight();
            int viewPosition = this.getScrollY() + view.getScrollY() + view.getHeight();
            int percentageSeen = (int) ((double) viewPosition / scrollViewHeight * 100);
            onViewSeenListener.onViewSeen(view, percentageSeen);
            return true;
        }
        return false;
    }

    public void registerViewSeenCallBack(final ArrayList<View> views, final OnViewSeenListener onViewSeenListener) {

        final boolean[] viewSeen = new boolean[views.size()];

        FocusAwareScrollView.this.postDelayed(new Runnable() {
            @Override
            public void run() {

                final Rect scrollBounds = new Rect();
                FocusAwareScrollView.this.getHitRect(scrollBounds);
                final int loc[] = new int[2];
                FocusAwareScrollView.this.getLocationOnScreen(loc);

                FocusAwareScrollView.this.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {

                    boolean allViewsSeen = true;

                    @Override
                    public void onScrollChange(NestedScrollView v, int x, int y, int oldx, int oldy) {

                        for (int index = 0; index < views.size(); index++) {

                            //Change this to adjust criteria
                            float viewSeenPercent = 1;

                            if (!viewSeen[index])
                                viewSeen[index] = handleViewSeenEvent(views.get(index), scrollBounds.bottom, loc[1], viewSeenPercent, onViewSeenListener);

                            if (!viewSeen[index])
                                allViewsSeen = false;
                        }

                        //Remove this if you want continuous callbacks
                        if (allViewsSeen)
                            FocusAwareScrollView.this.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) null);
                    }
                });
            }
        }, 500);
    }
}

1

কোটলিন উপায়;

স্ক্রোল ভিউয়ের স্ক্রোল তালিকাভুক্ত করার জন্য একটি এক্সটেনশান এবং স্ক্রিনে চাইল্ড ভিউ দৃশ্যমান হলে একটি ক্রিয়া পান।

@SuppressLint("ClickableViewAccessibility")
fun View.setChildViewOnScreenListener(view: View, action: () -> Unit) {
    val visibleScreen = Rect()

    this.setOnTouchListener { _, motionEvent ->
        if (motionEvent.action == MotionEvent.ACTION_MOVE) {
            this.getDrawingRect(visibleScreen)

            if (view.getLocalVisibleRect(visibleScreen)) {
                action()
            }
        }

        false
    }
}

যে কোনও স্ক্রোলযোগ্য দৃশ্যের জন্য এই এক্সটেনশন ফাংশনটি ব্যবহার করুন

nestedScrollView.setChildViewOnScreenListener(childView) {
               action()
            }

0

আমি জানি এটা খুব দেরী। তবে আমার একটি ভাল সমাধান আছে। নীচে স্ক্রোল ভিউতে দৃশ্যমানতার শতাংশের জন্য কোড স্নিপেট রয়েছে।

স্ক্রোল স্টপের কলব্যাক পাওয়ার জন্য প্রথমে স্ক্রোল ভিউতে স্পর্শ শ্রোতা সেট করুন।

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch ( event.getAction( ) ) {
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    if(mScrollView == null){
                        mScrollView = (ScrollView) findViewById(R.id.mScrollView);
                    }
                    int childCount = scrollViewRootChild.getChildCount();

                    //Scroll view location on screen
                    int[] scrollViewLocation = {0,0};
                    mScrollView.getLocationOnScreen(scrollViewLocation);

                    //Scroll view height
                    int scrollViewHeight = mScrollView.getHeight();
                    for (int i = 0; i < childCount; i++){
                        View child = scrollViewRootChild.getChildAt(i);
                        if(child != null && child.getVisibility() == View.VISIBLE){
                            int[] viewLocation = new int[2];
                            child.getLocationOnScreen(viewLocation);
                            int viewHeight = child.getHeight();
                            getViewVisibilityOnScrollStopped(scrollViewLocation, scrollViewHeight,
                                    viewLocation, viewHeight, (String) child.getTag(), (childCount - (i+1)));
                        }
                    }
                }
            }, 150);
            break;
    }
    return false;
}

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

/**
 * getViewVisibilityOnScrollStopped
 * @param scrollViewLocation location of scroll view on screen
 * @param scrollViewHeight height of scroll view
 * @param viewLocation location of view on screen, you can use the method of view claas's getLocationOnScreen method.
 * @param viewHeight height of view
 * @param tag tag on view
 * @param childPending number of views pending for iteration.
 */
void getViewVisibilityOnScrollStopped(int[] scrollViewLocation, int scrollViewHeight, int[] viewLocation, int viewHeight, String tag, int childPending) {
    float visiblePercent = 0f;
    int viewBottom = viewHeight + viewLocation[1]; //Get the bottom of view.
    if(viewLocation[1] >= scrollViewLocation[1]) {  //if view's top is inside the scroll view.
        visiblePercent = 100;
        int scrollBottom = scrollViewHeight + scrollViewLocation[1];    //Get the bottom of scroll view 
        if (viewBottom >= scrollBottom) {   //If view's bottom is outside from scroll view
            int visiblePart = scrollBottom - viewLocation[1];  //Find the visible part of view by subtracting view's top from scrollview's bottom  
            visiblePercent = (float) visiblePart / viewHeight * 100;
        }
    }else{      //if view's top is outside the scroll view.
        if(viewBottom > scrollViewLocation[1]){ //if view's bottom is outside the scroll view
            int visiblePart = viewBottom - scrollViewLocation[1]; //Find the visible part of view by subtracting scroll view's top from view's bottom
            visiblePercent = (float) visiblePart / viewHeight * 100;
        }
    }
    if(visiblePercent > 0f){
        visibleWidgets.add(tag);        //List of visible view.
    }
    if(childPending == 0){
        //Do after iterating all children.
    }
}

আপনি যদি এই কোডটিতে কোনও উন্নতি অনুভব করেন তবে দয়া করে অবদান রাখুন।


0

আমি জাভা উত্তরগুলির দুটি (@ বিল-মোট https://stackoverflow.com/a/12428154/3686125 এবং @ denys-vasylenko https://stackoverflow.com/a/25528434/3686125 ) এর সংমিশ্রণটি প্রয়োগ করে শেষ করেছি আমার প্রকল্পটি কোটলিন এক্সটেনশনের সেট হিসাবে যা স্ট্যান্ডার্ড ভার্চিয়াল স্ক্রোলভিউ বা হরাইজেন্টালস্ক্রোলভিউ নিয়ন্ত্রণগুলিকে সমর্থন করে।

আমি এগুলি কেবল এক্সটেনশনস.কেটি নামে একটি কোটলিন ফাইলে ফেলেছি, কোনও শ্রেণি নেই, কেবল পদ্ধতি।

কোনও ব্যবহারকারী যখন আমার প্রকল্পের বিভিন্ন স্ক্রোলভিউতে স্ক্রোলিং বন্ধ করে দেয় তখন কোন আইটেমটি স্ন্যাপ করতে হবে তা নির্ধারণ করতে আমি এগুলি ব্যবহার করেছি:

fun View.isPartiallyOrFullyVisible(horizontalScrollView: HorizontalScrollView) : Boolean {
    @Suppress("CanBeVal") var scrollBounds = Rect()
    horizontalScrollView.getHitRect(scrollBounds)
    return getLocalVisibleRect(scrollBounds)
}

fun View.isPartiallyOrFullyVisible(scrollView: ScrollView) : Boolean {
    @Suppress("CanBeVal") var scrollBounds = Rect()
    scrollView.getHitRect(scrollBounds)
    return getLocalVisibleRect(scrollBounds)
}

fun View.isFullyVisible(horizontalScrollView: HorizontalScrollView) : Boolean {
    @Suppress("CanBeVal") var scrollBounds = Rect()
    horizontalScrollView.getDrawingRect(scrollBounds)
    val left = x
    val right = left + width
    return scrollBounds.left < left && scrollBounds.right > right
}

fun View.isFullyVisible(scrollView: ScrollView) : Boolean {
    @Suppress("CanBeVal") var scrollBounds = Rect()
    scrollView.getDrawingRect(scrollBounds)
    val top = y
    val bottom = top + height
    return scrollBounds.top < top && scrollBounds.bottom > bottom
}

fun View.isPartiallyVisible(horizontalScrollView: HorizontalScrollView) : Boolean = isPartiallyOrFullyVisible(horizontalScrollView) && !isFullyVisible(horizontalScrollView)
fun View.isPartiallyVisible(scrollView: ScrollView) : Boolean = isPartiallyOrFullyVisible(scrollView) && !isFullyVisible(scrollView)

ব্যবহারের উদাহরণ, স্ক্রোলভিউর লিনিয়ারলআউট শিশুদের মাধ্যমে পুনরাবৃত্তি এবং লগিং আউটপুট:

val linearLayoutChild: LinearLayout = getChildAt(0) as LinearLayout
val scrollView = findViewById(R.id.scroll_view) //Replace with your scrollview control or synthetic accessor
for (i in 0 until linearLayoutChild.childCount) {
    with (linearLayoutChild.getChildAt(i)) {
        Log.d("ScrollView", "child$i left=$left width=$width isPartiallyOrFullyVisible=${isPartiallyOrFullyVisible(scrollView)} isFullyVisible=${isFullyVisible(scrollView)} isPartiallyVisible=${isPartiallyVisible(scrollView)}")
    }
}

1
আপনি আদর্শ varইঙ্গিতটি কেন ব্যবহার করছেন এবং দমন করছেন ?
ফিলিপকোইচিজ

-1

@ কিবার্টিকাস উত্তরটি ব্যবহার করে যা পয়েন্টটি ছিল তবে দুর্দান্ত বিটিডাব্লু, আমি যখনই কোনও স্ক্রোলভিউ কল করা হয় এবং স্ক্রলড হয় তা পরীক্ষা করার জন্য কোডের একগুচ্ছ সংকলন করেছিলাম @ কবার্টিকাস উত্তরটি ট্রিগার করে এবং আপনি যা চান তা করতে পারেন, আমার ক্ষেত্রে আমার কাছে একটি আছে ভিডিওগুলিতে থাকা সোশ্যাল নেটওয়ার্ক যাতে স্ক্রিনে দৃশ্যটি আঁকলে আমি ভিডিওটি ফেসবুক এবং ইনস্টাগ্রামের মতো একই ধারণা খেলি। কোডটি এখানে:

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

                    @Override
                    public void onScrollChanged() {
                        //mainscrollview is my scrollview that have inside it a linearlayout containing many child views.
                        Rect bounds = new Rect();
                         for(int xx=1;xx<=postslayoutindex;xx++)
                         {

                          //postslayoutindex is the index of how many posts are read.
                          //postslayoutchild is the main layout for the posts.
                        if(postslayoutchild[xx]!=null){

                            postslayoutchild[xx].getHitRect(bounds);

                        Rect scrollBounds = new Rect();
                        mainscrollview.getDrawingRect(scrollBounds);

                        if(Rect.intersects(scrollBounds, bounds))
                        {
                            vidPreview[xx].startPlaywithoutstoppping();
                         //I made my own custom video player using textureview and initialized it globally in the class as an array so I can access it from anywhere.
                        }
                        else
                        {

                        }


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