Igor Janković
Igor Janković

Reputation: 5532

Get first visible view inside of NestedScrollView

I have a next problem.

I'm trying to get first visible item inside of NestedScrollView. Actually, first and only view inside is LinearLayout (because scroll view can hold only one direct child), but I'm trying to get first visible item inside it. I was searching a lot but without success.

With this approach, I want to avoid using RecyclerView inside another RecyclerView. I found it is a bad practice.

P.S. I don't want to use ListView or RecyclerView

Thanks in advance

Upvotes: 1

Views: 3890

Answers (3)

Igor Janković
Igor Janković

Reputation: 5532

Okay, I found a solution:

        final Rect scrollBounds = new Rect();
        questionAndAnswerScroll.getHitRect(scrollBounds);
        questionAndAnswerScroll.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
            @Override
            public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                for (int i = 0; i < questionAndAnswerHolder.getChildCount(); i++) {
                    View childView = questionAndAnswerHolder.getChildAt(i);
                    if (childView != null) {
                        if (childView.getLocalVisibleRect(scrollBounds)) {
                            //Here is the position of first visible view
                            positionToScroll = i;
                            break;
                        }
                    }
                }
            }
        });

Upvotes: 6

Rasoul Miri
Rasoul Miri

Reputation: 12222

for this layout

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/nestedScrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/ly"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="text_1"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="text_2" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="text_3" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="text_4" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="text_5" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="text_6" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="text_7" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="text_8" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="text_9" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="text_10" />


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

and use this code

  public class MainActivity extends AppCompatActivity {

    NestedScrollView nestedScrollView;
    LinearLayout linearLayout;

    ArrayList<Integer> childrenY = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //find view
        nestedScrollView = (NestedScrollView) findViewById(R.id.nestedScrollView);
        linearLayout = (LinearLayout) nestedScrollView.getChildAt(0);


        //get Y Children and save
        for (int i = 0; i < linearLayout.getChildCount(); i++) {

            int childrenY = 0;
            for (int j = 0; j < i; j++) {
                TextView tv = (TextView) linearLayout.getChildAt(j);
                Log.i("--------", tv.getText().toString());
                childrenY += tv.getLayoutParams().height;
            }
            this.childrenY.add(childrenY);
        }

        //add Scroll Change Listener
        nestedScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
            @Override
            public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {

                for (int i = 0; i < childrenY.size(); i++) {
                    if (scrollY < childrenY.get(i)) {
                        Log.i("++++++++++", ((TextView) linearLayout.getChildAt(i-1)).getText().toString());
                        return;
                    }
                }
            }
        });
    }
}

Upvotes: 1

SiSa
SiSa

Reputation: 2684

If you want to find the first visible item inside inner LinearLayout of NestedScrollView, you may try this:

    if(nsv.getChildCount() > 0) {
        ViewGroup vg = (ViewGroup) nsv.getChildAt(0);
        for (int i = 0; i < vg.getChildCount(); i++) {
            if(vg.getChildAt(i).getVisibility()==View.VISIBLE)
                return vg.getChildAt(i);
        }
    }

    return null;

Where nsv is your NestedScrollView.

Upvotes: 0

Related Questions