viewholder recyclerview holder getadapterposition from child android scroll position android-recyclerview

holder - Android: ¿Cómo obtener el desplazamiento X actual de RecyclerView?



getadapterposition (6)

Estoy usando una Scrollview de Scrollview para un "carrusel Scrollview de tiempo" infinito y descubrí que no es el mejor enfoque ( última pregunta )

Ahora, encontré la Vista del reciclador, pero no puedo obtener el desplazamiento del desplazamiento actual en la dirección X de la vista del reciclador . (Digamos que cada elemento tiene un ancho de 100 px y el segundo elemento solo es visible al 50%, por lo que el desplazamiento del desplazamiento es de 150 px)

  • Todos los artículos tienen el mismo ancho, pero hay algún espacio antes del primero, después del último artículo
  • recyclerView.getScrollX() devuelve 0 (los documentos dicen: valor de desplazamiento inicial)
  • LayoutManager tiene findFirstVisibleItemPosition , pero no puedo calcular el desplazamiento de X con eso

ACTUALIZAR

¡Acabo de encontrar una manera de seguir rastreando la posición X, mientras actualizo el valor con la onScrolled llamada onScrolled , pero preferiría obtener el valor real en lugar de rastrearlo todo el tiempo!

private int overallXScroll = 0; //... mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); overallXScroll = overallXScroll + dx; Log.i("check","overallXScroll->" + overallXScroll); } });


¡Gracias a @ umar-qureshi por el liderazgo correcto! Parece que puede determinar el porcentaje de desplazamiento con Offset , Extent y Range manera que

percentage = 100 * offset / (range - extent)

Por ejemplo (para poner en un OnScrollListener ):

int offset = recyclerView.computeVerticalScrollOffset(); int extent = recyclerView.computeVerticalScrollExtent(); int range = recyclerView.computeVerticalScrollRange(); int percentage = (int)(100.0 * offset / (float)(range - extent)); Log.i("RecyclerView, "scroll percentage: "+ percentage + "%");


RecyclerView ya tiene un método para obtener desplazamiento de desplazamiento horizontal y vertical

mRecyclerView.computeHorizontalScrollOffset() mRecyclerView.computeVerticalScrollOffset()

Esto funcionará para RecyclerViews que contienen celdas de la misma altura (para desplazamiento de desplazamiento vertical) y el mismo ancho (para desplazamiento de desplazamiento horizontal)


Si necesita conocer la página actual y su desplazamiento en comparación con el ancho de RecyclerView, puede intentar algo como esto:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); final int scrollOffset = recyclerView.computeHorizontalScrollOffset(); final int width = recyclerView.getWidth(); final int currentPage = scrollOffset / width; final float pageOffset = (float) (scrollOffset % width) / width; // the following lines just the example of how you can use it if (currentPage == 0) { leftIndicator.setAlpha(pageOffset); } if (adapter.getItemCount() <= 1) { rightIndicator.setAlpha(pageOffset); } else if (currentPage == adapter.getItemCount() - 2) { rightIndicator.setAlpha(1f - pageOffset); } } });

Si currentPage tiene el índice 0, leftIndicator (flecha) será transparente, y también lo será y rightIndicator si solo hay una page (en el ejemplo, el adaptador siempre tiene al menos un elemento para mostrar, por lo que no se verifica el valor vacío).

De esta manera, básicamente tendrá casi la misma funcionalidad que si hubiera estado utilizando la página de devolución de llamada pageScrolled desde ViewPager.OnPageChangeListener .


anulando RecyclerView onScrolled(int dx,int dy) , puede obtener el desplazamiento del desplazamiento. pero cuando agrega o elimina el elemento, el valor puede ser incorrecto.

public class TempRecyclerView extends RecyclerView { private int offsetX = 0; private int offsetY = 0; public TempRecyclerView(Context context) { super(context); } public TempRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public TempRecyclerView(Context context, @Nullable AttributeSet attrs,int defStyle){ super(context, attrs, defStyle); } /** * Called when the scroll position of this RecyclerView changes. Subclasses should usethis method to respond to scrolling within the adapter''s data set instead of an explicit listener. * <p>This method will always be invoked before listeners. If a subclass needs to perform any additional upkeep or bookkeeping after scrolling but before listeners run, this is a good place to do so.</p> */ @Override public void onScrolled(int dx, int dy) { // super.onScrolled(dx, dy); offsetX+=dx; offsetY+=dy; } }


Solución 1: setOnScrollListener

Guarde su posición X como variable de clase y actualice cada cambio dentro de onScrollListener . Asegúrese de no restablecer overallXScroll (por onScreenRotationChange )

private int overallXScroll = 0; //... mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); overallXScroll = overallXScroll + dx; Log.i("check","overall X = " + overallXScroll); } });

Solución 2: Calcular la posición actual.

En mi caso, tengo una Lista horizontal que está llena de valores de tiempo (0:00, 0:30, 1:00, 1:30 ... 23:00, 23:30). Estoy calculando el tiempo a partir del elemento de tiempo, que se encuentra en el medio de la pantalla (punto de cálculo). Es por eso que necesito la posición exacta de X-Scroll de mi RecycleView

  • Cada elemento de tiempo tiene el mismo ancho de 60dp (para su información: 60dp = 30min, 2dp = 1min)
  • El primer elemento (elemento de encabezado) tiene un relleno adicional, para establecer 0 minutos al centro

    private int mScreenWidth = 0; private int mHeaderItemWidth = 0; private int mCellWidth = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //init recycle views //... LinearLayoutManager mLLM = (LinearLayoutManager) getLayoutManager(); DisplayMetrics displaymetrics = new DisplayMetrics(); this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); this.mScreenWidth = displaymetrics.widthPixels; //calculate value on current device mCellWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getResources() .getDisplayMetrics()); //get offset of list to the right (gap to the left of the screen from the left side of first item) final int mOffset = (this.mScreenWidth / 2) - (mCellWidth / 2); //HeaderItem width (blue rectangle in graphic) mHeaderItemWidth = mOffset + mCellWidth; mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); //get first visible item View firstVisibleItem = mLLM.findViewByPosition(mLLM.findFirstVisibleItemPosition()); int leftScrollXCalculated = 0; if (firstItemPosition == 0){ //if first item, get width of headerview (getLeft() < 0, that''s why I Use Math.abs()) leftScrollXCalculated = Math.abs(firstVisibleItem.getLeft()); } else{ //X-Position = Gap to the right + Number of cells * width - cell offset of current first visible item //(mHeaderItemWidth includes already width of one cell, that''s why I have to subtract it again) leftScrollXCalculated = (mHeaderItemWidth - mCellWidth) + firstItemPosition * mCellWidth + firstVisibleItem.getLeft(); } Log.i("asdf","calculated X to left = " + leftScrollXCalculated); } });

    }


public class CustomRecyclerView extends RecyclerView { public CustomRecyclerView(Context context) { super(context); } public CustomRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public int getHorizontalOffset() { return super.computeHorizontalScrollOffset(); } }

De donde necesita obtener el desplazamiento:

recyclerView.getHorizontalOffset()