22 votes

La création d'un verrouillée ScrollView dans Android

Je suis en train de mettre en œuvre un ScrollView dans Android qui n'a pas de défilement lors de l'ajout d'un élément au-dessus de la position de défilement actuelle.

L'implémentation par défaut de ScrollView se comporte comme suit:

L'ajout d'un élément au-dessus de la position de défilement actuelle: enter image description here

L'ajout d'un élément au-dessous de la position de défilement actuelle: enter image description here

Comment puis-je "verrouiller" l' ScrollView avant l'ajout d'un élément au-dessus de la position de défilement actuelle?

C'est mon fichier de mise en page, j'ai actuellement substituée à la fois l' ScrollView et LinearLayout, mais n'avez pas fait de modifications encore.

<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>

Exemple De Code Source: https://github.com/Amaros90/android-lockable-scroller-poc

Merci!!!!

16voto

MTZ4 Points 1083

Vous pouvez facilement obtenir le comportement opposé en utilisant addOnLayoutChangeListener de votre LinearLayout et réinitialiser l' ScrollViews' ScrollY. Ici est la mise en œuvre dans votre 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);
}

Alors vous pouvez facilement le drapeau de l' addToEnd de la fonction ou de vérifier si l'enfant a été ajouté pour éviter la modification de défilement quand un enfant est ajouté à la partie inférieure.

1voto

umitems Points 768

Vous pouvez essayer d'utiliser l' RecyclerView et de mettre en oeuvre onDataSetChanged(). Alors détecter si add to TOP ou add to END bouton a été pressé. Ensuite, utilisez scrollToPositionWithOffset(int, int) de gérer le défilement.

Par exemple:

//Scroll item 3 to 20 pixels from the top
linearLayoutManager.scrollToPositionWithOffset(3, 20);

Pour la restauration de la position de défilement d'un RecyclerView, c'est la façon d'enregistrer les positions de défilement (les deux arguments de la méthode de scrollToPositionWithOffset(int, int)):

int index = linearLayoutManager.findFirstVisibleItemPosition(); 
View v = linearLayoutManager.getChildAt(0); 
int top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop())

1voto

Amaros Points 175

La mise en œuvre de cette travaillé pour moi. Vous pouvez consulter l'exemple d'application, j'ai ajouté dans la question d'origine.

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);
                            }
                        });
                    }
                }
            }
        });
    }
}

0voto

Techno Addict Points 34

vous pouvez le faire facilement l'obtenir..

tout d'abord dans l'événement onclick de stocker la valeur int par à l'aide de getFirstVisiblePosition()

exemple.

dans le onclick d'ajouter un bouton de l'élément le faire---

int currentpos = recycleview.getFirstVisiblePosition();

maintenant, après que vous insérez elment à la liste/recyclerview---

recyclerview.scrolltoposition(currentpos);

c'est ça, essayez si vous voulez le faire sans erreur..

Bonne Chance :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X