programacion - scrollview android fillviewport
Creando un ScrollView bloqueado en Android (4)
Estoy intentando implementar un ScrollView
en Android que no se desplaza cuando se agrega un elemento por encima de la posición de desplazamiento actual.
La implementación predeterminada de ScrollView
comporta de la siguiente manera:
Adición de un elemento por encima de la posición de desplazamiento actual:
Agregar un elemento debajo de la posición de desplazamiento actual:
¿Cómo puedo "bloquear" el ScrollView
antes de agregar un elemento por encima de la posición de desplazamiento actual?
Este es mi archivo de diseño, actualmente he anulado tanto ScrollView
como LinearLayout
, pero todavía no he realizado ninguna modificación.
<LinearLayout
android:layout_height="fill_parent"
android:orientation="vertical"
android:layout_width="fill_parent">
<LinearLayout
android:id="@+id/LinearLayout02"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_alignParentBottom="true">
<Button
android:id="@+id/Button02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" android:text="Add To Top"
android:onClick="addToStart">
</Button>
<Button
android:id="@+id/Button03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Add to End"
android:onClick="addToEnd">
</Button>
</LinearLayout>
<com.poc.scroller.locable.lockablescrollerpoc.LockedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:verticalScrollbarPosition="right"
android:fadeScrollbars="false"
android:background="@color/scrollColor">
<com.poc.scroller.locable.lockablescrollerpoc.LockedLinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/Container">
</com.poc.scroller.locable.lockablescrollerpoc.LockedLinearLayout>
</com.poc.scroller.locable.lockablescrollerpoc.LockedScrollView>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Código fuente de ejemplo: https://github.com/Amaros90/android-lockable-scroller-poc
¡Gracias!
Implementar esto funcionó para mí. Puedes ver la aplicación de ejemplo que agregué en la pregunta original.
public class LockableScrollView extends ScrollView {
private boolean _enabled = true;
public LockableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
super.setFillViewport(true);
}
@Override
public void addView(View layout, ViewGroup.LayoutParams params) {
super.addView(layout, params);
((ViewGroup)layout).setOnHierarchyChangeListener(new OnHierarchyChangeListener() {
@Override
public void onChildViewAdded(View layout, View item) {
if (_enabled) {
item.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View item, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
item.removeOnLayoutChangeListener(this);
int scrollViewY = ((LockableScrollView)item.getParent().getParent()).getScrollY();
int layoutPosition = ((View)item.getParent()).getTop();
boolean shouldScroll = item.getTop() + layoutPosition <= scrollViewY || item.getBottom() + getTop() <= scrollViewY;
if (shouldScroll) {
final int childViewHeight = item.getHeight();
((View)item.getParent()).addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View layout, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
layout.removeOnLayoutChangeListener(this);
LockableScrollView scrollView = ((LockableScrollView)layout.getParent());
scrollView.scrollTo(scrollView.getScrollX(), scrollView.getScrollY() + childViewHeight);
}
});
}
}
});
}
}
@Override
public void onChildViewRemoved(View layout, View item) {
if (_enabled) {
int scrollViewY = ((LockableScrollView)layout.getParent()).getScrollY();
int layoutPosition = layout.getTop();
boolean shouldScroll = item.getTop() + layoutPosition <= scrollViewY || item.getBottom() + getTop() <= scrollViewY;
if (shouldScroll) {
final int childViewHeight = item.getHeight();
layout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View layout, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
layout.removeOnLayoutChangeListener(this);
LockableScrollView scrollView = ((LockableScrollView)layout.getParent());
scrollView.scrollTo(scrollView.getScrollX(), scrollView.getScrollY() - childViewHeight);
}
});
}
}
}
});
}
}
Puede intentar usar RecyclerView
e implementar onDataSetChanged()
. A continuación, detecte si se presionó add to TOP
o add to END
botón. Luego use scrollToPositionWithOffset(int, int)
para administrar el scroll.
Por ejemplo:
//Scroll item 3 to 20 pixels from the top
linearLayoutManager.scrollToPositionWithOffset(3, 20);
Para restaurar la posición de desplazamiento de un RecyclerView
, esta es la forma de guardar las posiciones de desplazamiento (los dos argumentos para el método scrollToPositionWithOffset(int, int)
):
int index = linearLayoutManager.findFirstVisibleItemPosition();
View v = linearLayoutManager.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop())
Puede obtener fácilmente el comportamiento opuesto utilizando addOnLayoutChangeListener
de su LinearLayout
y reinicie LinearLayout
ScrollView
. Aquí está la implementación en su ScrollViewActivity.onCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.scrollview);
_linearLayout = (LockedLinearLayout)findViewById(R.id.Container);
_scrollView = (LockedScrollView)findViewById(R.id.ScrollView);
_layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
_linearLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
_scrollView.scrollTo(0, _scrollView.getScrollY() + (bottom - oldBottom ));
}
});
addExampleImage(10, _linearLayout);
}
Luego, puede marcar fácilmente la función addToEnd
o verificar dónde se agregó el niño para evitar cambiar de desplazamiento cuando se agrega algún niño en la parte inferior.
Puedes hacerlo fácilmente solo tienes que conseguirlo ..
En primer lugar, en el evento onclick, almacene el valor int utilizando getFirstVisiblePosition ()
ejemplo.
en un clic en el botón Agregar elemento haga esto ---
int currentpos = recycleview.getFirstVisiblePosition ();
ahora después de insertar elment a list / recyclerview ---
recyclerview.scrolltoposition (currentpos);
eso es intentarlo si quieres hacerlo sin error ...
Buena suerte :)