如何在scrollChange事件上获取android Horizo​​ntal scrollview的First Visible子项

时间:2018-09-29 04:57:18

标签: android horizontalscrollview

我需要在scrollChange事件上找到android Horizo​​ntal scrollview的第一个可见子项。我已点击此链接How to get First Visible child item of android scrollview on scrollChange event 但是找不到rowView是什么。

    horizontalScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
    @Override
    public void onScrollChanged() {
        int scrollPos = horizontalScrollView1.getScrollX();
        Log.e("scroll x:", scrollPos + "");           
    }
});

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <HorizontalScrollView
        android:id="@+id/horizontalScrollView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="15dp"
        android:fillViewport="true"
        android:scrollbars="none">
        <RelativeLayout
        android:id="@+id/layLandmarks"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
            <View
                android:id="@+id/viewWhite"
                android:layout_width="match_parent"
                android:layout_height="10dp"
                android:layout_centerInParent="true"
                android:background="@color/white" />

        </RelativeLayout>
    </HorizontalScrollView>   
</RelativeLayout>

类文件:

    ImageView iv;
RelativeLayout layLandmarks = (RelativeLayout) findViewById(R.id.layLandmarks);
FrameLayout.LayoutParams lp1 = new FrameLayout.LayoutParams(2000, FrameLayout.LayoutParams.WRAP_CONTENT);
layLandmarks.setLayoutParams(lp1);
JSONObject landmarks = jsonObject1.getString("landmarks");
JSONArray jsonArray1 = new JSONArray(landmarks);
for (int j = 0; j < jsonArray1.length(); j++) {
JSONObject jsonObject2 = jsonArray1.getJSONObject(0);

landmarkId = jsonObject2.getString("id");
landmarkName = jsonObject2.getString("title");
landmarkDesc = jsonObject2.getString("description");
latitude = jsonObject2.getDouble("latitude");
longitude = jsonObject2.getDouble("longitude");
video_time = jsonObject2.getString("video_time_in_sec");
//   Log.e("video_time_in_sec", video_time);
landmarkIcon = jsonObject2.getString("image");
iv = new ImageView(VideoPreviewWithRecycler.this);
iv.setId(i);
Picasso
        .with(VideoPreviewWithRecycler.this)
        .load(landmarkIcon)
        .resize(40, 45)
        .into(iv);
params = new RelativeLayout.LayoutParams(40, 45);

params.topMargin = 0;

params.leftMargin = Integer.parseInt(video_time);
params.addRule(RelativeLayout.RIGHT_OF, 0);

layLandmarks.addView(iv, params);
}

更新:

 horizontalScrollView1.setOnScrollChangeListener(new View.OnScrollChangeListener() {
                        @Override
                        public void onScrollChange(View v, final int scrollX, int scrollY, final int oldScrollX, int oldScrollY) {

                            horizontalScrollView1.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                                @Override
                                public void onGlobalLayout() {

                                   int firstVisibleItemIndex= getFirstVisibleItem1(horizontalScrollView1);
                                   Log.e("firstVisibleItemIndex >>",firstVisibleItemIndex+"");
                                }

                            });
                        }
                    });


 private int getFirstVisibleItem1(HorizontalScrollView scrollView) {
        ViewGroup viewGroup = (ViewGroup) scrollView.getChildAt(0); // cast to ViewGroup here because I think we only need to getFirstVisibleItem if ScrollView have multiple items
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View view = viewGroup.getChildAt(i);
            if (view.getX() + view.getWidth() >= scrollView.getScrollX()) {
                return i; // if you want to receive the position, return  i here
            }
        }
        return 0;
    }

4 个答案:

答案 0 :(得分:0)

我认为这可能会有所帮助

private View getFirstVisibleItem(HorizontalScrollView scrollView) {
    ViewGroup viewGroup = (ViewGroup) scrollView.getChildAt(0); // cast to ViewGroup here because I think we only need to getFirstVisibleItem if ScrollView have multiple items
    for (int i = 0; i < viewGroup.getChildCount(); i++) {
        View view = viewGroup.getChildAt(i);
        if (view.getX() + view.getWidth() >= scrollView.getScrollX()) {
            return view; // if you want to receive the position, return turn i here
        }
    }
    return null;
}

这个想法是检查每个view x positionscroll x value

答案 1 :(得分:0)

我在我的应用程序中实现了一些基本的滚动动画。我使用了这段代码,它运行正常。

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, 
LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(linearLayoutManager);




 recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            switch (newState) {
                case RecyclerView.SCROLL_STATE_IDLE:
                case RecyclerView.SCROLL_STATE_DRAGGING:
                case RecyclerView.SCROLL_STATE_SETTLING:
            currentItemPosition=linearLayoutManager.findFirstCompletelyVisibleItemPosition();

            }
        }

我的要求是在滚动稳定期间找到位置,您可以在SCROLL_STATE_IDLE期间尝试相同的位置

答案 2 :(得分:0)

方法很少,但我只喜欢一种。

所有视图均具有“ boolean View.getGlobalVisibleRect(..)”(https://developer.android.com/reference/android/view/View.html#getGlobalVisibleRect(android.graphics.Rect))方法,如果该视图被其父级完全隐藏,则返回FALSE。

因此,所有Horizo​​ntalScrollView的子级都具有该HScrollView作为其父级,如果该方法返回FALSE,则意味着View不可见。返回TRUE的第一个孩子是该HScrollView内部的第一个可见孩子。

答案 3 :(得分:0)

您可以使用Linearlayout代替RelaytiveLayout作为HorizontalScrollView的子级。像这样:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <HorizontalScrollView
        android:id="@+id/horizontalScrollView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none">

        <LinearLayout
            android:id="@+id/layLandmarks"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:padding="16dp" />

    </HorizontalScrollView>

</RelativeLayout>

注意:在嵌套版式的情况下,您还可以使用自定义版式在LinearLayout中的视图中进行充气,以提高性能。 (我在这里使用的是TextView而非自定义布局)

在您的活动中使用类似以下的内容:

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

    final HorizontalScrollView horizontalScrollView = findViewById(R.id.horizontalScrollView);
    TextView iv;
    final LinearLayout layLandmarks = findViewById(R.id.layLandmarks);
    for (int j = 0; j < 10; j++) {
        iv = new TextView(this);
        iv.setId(j);
        iv.setText("TEXT " + j);
        iv.setPadding(20, 20, 20, 20);
        layLandmarks.addView(iv);
    }

    horizontalScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            int firstVisibleItemIndex = getFirstVisibleItem(layLandmarks, horizontalScrollView);
            Log.e("ItemIndex >>", firstVisibleItemIndex + "");
        }
    });
}

现在使用下面的代码。它修改了 @Pan Van Linh 答案的版本。

private int getFirstVisibleItem(LinearLayout linearLayout, HorizontalScrollView horizontalScrollView) {
    for (int i = 0; i < linearLayout.getChildCount(); i++) {
        View view = linearLayout.getChildAt(i);
        if (view.getX() + view.getWidth() >= horizontalScrollView.getScrollX()) {
            return i; // if you want to receive the position, return  i here
        }
    }
    return 0;
}

我希望这可以解决您的问题。 :)