To tylko częściowa odpowiedź; Brakuje mi (przynajmniej) jednego kawałka układanki, ale mam nadzieję, że ktoś inny to wymyśli.
Po dodaniu niezbędne atrybuty tagu <RecyclerView>
(jak wspomniano w odpowiedzi związanej z pytaniem OP), wymiarowania/pozycjonowanie kciuka paska przewijania jest kontrolowana przez trzech metod wewnątrz LinearLayoutManager
:
int computeVerticalScrollRange()
: Rozmiar ścieżki paska przewijania.
int computeVerticalScrollExtent()
: Wielkość kciuka paska przewijania.
int computeVerticalScrollOffset()
: Odległość między górną częścią ścieżki paska przewijania i górną częścią kciuka paska przewijania.
Jednostki dla tych metod są arbitralne; możesz używać wszystkiego, co chcesz, o ile wszystkie trzy metody dzielą te same jednostki. Domyślnie LinearLayoutManager
będzie użyć jednego z dwóch zestawów jednostek:
mSmoothScrollbarEnabled == true
: używać jednostek w oparciu o wielkości piksela widocznych elementów w RecyclerView
.
mSmoothScrollbarEnabled == false
: Użyj jednostek na podstawie pozycji widocznych elementów w adapterze RecyclerView
.
Aby kontrolować wielkość kciuka pasek przewijania za siebie, będziesz musiał zastąpić te metody ... ale oto kawałek mi brakuje: We wszystkich moich eksperymentów, computeVerticalScrollExtent()
nigdy nie jest wywoływana przez system. To powiedziawszy, nadal możemy pokazać tutaj pewien postęp.
Najpierw utworzyłem prosty adapter, który pokazuje 500 CardView
s z pozycją przedmiotu w środku. Włączam szybkie przewijanie za pomocą naprawdę prostych (ale brzydkich) rysunków. Oto co przewijania wygląda tylko z realizacji domyślny LinearLayoutManager
:
Jak już stwierdzono, 500 (małych) przedmiotów, kciuk przewijania jest bardzo mały i bardzo ciężko dotknąć. Możemy uczynić pasek przewijania znacznie większym przez przesłonięcie computeVerticalScrollRange()
, aby zwrócić stałą stałą ...Wybrałem 5000
zasadniczo losowo tylko pokazać istotną zmianę:
Oczywiście, teraz pasek przewijania nie działa jak można się spodziewać; przewijanie listy przez przeciąganie jej w normalny sposób przesuwa kciuk o wiele bardziej niż powinien, a szybkie przewijanie listy przeciągając kciuk przesuwa listę o wiele mniej niż powinna.
na urządzeniu, z losowo wybranego zakresu 5000
, nadrzędnymi computeVerticalScrollOffset()
następująco czyni kciuk przewijania poruszać doskonale jak przewijać listę przeciągając na niego:
@Override
public int computeVerticalScrollRange(RecyclerView.State state) {
return 5000;
}
@Override
public int computeVerticalScrollOffset(RecyclerView.State state) {
return (int) (super.computeVerticalScrollOffset(state)/23.5f);
}
Jednak to nadal nie robi” t naprawić drugi problem: przeciąganie na kciuku nie powoduje właściwego przewijania listy. Jak wspomniałem powyżej, wydaje się, że właściwą rzeczą byłoby zastąpienie computeVerticalScrollExtent()
, ale system nigdy nie wywoła tej metody. Nawet przesłoniłem to, aby po prostu wyrzucić wyjątek, a moja aplikacja nigdy się nie zawiesza.
Mam nadzieję, że to przynajmniej pomoże wskazać ludzi we właściwym kierunku, aby uzyskać pełne rozwiązanie.
PS: Implementacje computeVerticalScrollRange()
i computeVerticalScrollOffset()
Zawarłem tę odpowiedź są celowo proste (czytaj: fałszywe). "Prawdziwe" implementacje byłyby znacznie bardziej złożone; domyślne implementacje LinearLayoutManager
uwzględniają orientację urządzenia, pierwsze i ostatnie widoczne elementy na liście, liczbę elementów poza ekranem w obu kierunkach, płynne przewijanie, różne flagi układu i tak dalej.
Ten sam problem w mojej aplikacji. Czy możemy zdefiniować kciuk poprawkowy, który nie zmniejsza się w zależności od rozmiaru listy? – egmontr
Ten sam problem w mojej aplikacji –
Powyższa odpowiedź jest bardzo ograniczona. Oto przykład (https://bitbucket.org/StylingAndroid/scrollingrecyclerview/src/2fc7d871b911144b492744bb3a5097bb01869ac1?at=Part1) tego, co chcesz zrobić. –