#android #scroll #android-listview #smooth-scrolling
#Android #прокрутка #android-listview #плавная прокрутка
Вопрос:
У меня есть ListView. Когда элемент находится в определенной позиции, он меняет цвет. (см. Рисунок).Вверху (с синими квадратами) — это то, что у меня есть сейчас. Вниз — то, что мне нужно. Но при прокрутке, когда элемент находится в нужном положении и меняет цвет, это происходит не плавно. Кажется, что элемент переходит в нужную позицию. Как я могу сделать этот процесс более плавным? Спасибо.
вот часть моего класса view:
public class TimeView extends View {
...........................
@Override
public void setOnScrollChangeListener(OnScrollChangeListener l) {
}
AbsListView.OnScrollListener scrollListener = new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(final AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
View childView = view.getChildAt(0);
int position = view.getFirstVisiblePosition();
if (-childView.getTop() > childView.getHeight() / 2) {
position ;
}
view.setSelection(position);
}
}
@Override
public void onScroll(final AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
for (int i = 0; i < view.getChildCount(); i ) {
View childView = view.getChildAt(i);
if (i == 1) {
childView.setBackgroundResource(R.drawable.selected_color);
} else {
childView.setBackgroundResource(R.drawable.no_select_color);
}
}
}
};
Ответ №1:
Попробуйте это:
@Override
public void onScrollStateChanged(final AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
View firstView = view.getChildAt(0);
Rect rect = new Rect(0, 0, firstView.getWidth(), firstView.getHeight());
view.getChildVisibleRect(firstView, rect, null);
int position = view.getFirstVisiblePosition();
if (rect.height() < (firstView.getHeight() / 2)) {
position ;
}
final int finalPosition = position;
view.postDelayed(new Runnable() {
@Override
public void run() {
view.smoothScrollToPositionFromTop(finalPosition, 0, 500);
}
}, 1);
}
}
Обновлено:
Приведенный выше код имеет постоянное время установления (500 мс). Приведенный ниже код имеет постоянную скорость привязки (0,2 пикселя / мс, это означает, что прокрутка вверх / вниз пикселя занимает 5 мс).
final static int SCROLL_TIME_PER_PIXEL = 5; // Time(ms) to snap a pixel.
@Override
public void onScrollStateChanged(final AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
View firstView = view.getChildAt(0);
Rect rect = new Rect(0, 0, firstView.getWidth(), firstView.getHeight());
view.getChildVisibleRect(firstView, rect, null);
int position = view.getFirstVisiblePosition();
int offset = rect.height();
if (rect.height() < (firstView.getHeight() / 2)) {
position ;
} else offset = firstView.getHeight() - rect.height();
final int finalPosition = position; // Snap to position.
final int finalOffset = offset; // Snap distance in pixels.
view.postDelayed(new Runnable() {
@Override
public void run() {
view.smoothScrollToPositionFromTop(finalPosition, 0, finalOffset * SCROLL_TIME_PER_PIXEL);
}
}, 1);
}
}
Комментарии:
1. #i_A_mok, не могли бы вы, пожалуйста, объяснить, как работает этот метод? Спасибо
2. i_A_mok, спасибо. Я постараюсь сообщить о результатах
3. Я попытался воспользоваться вашим советом, и, похоже, он работает так, как мне нужно. Большое вам спасибо!
Ответ №2:
Если вы переключитесь на использование RecyclerView вместо ListView (что вам все равно следует делать), вы можете использовать SnapHelper
для этого:
SnapHelper helper = new LinearSnapHelper();
helper.attachToRecyclerView(recyclerView);
Комментарии:
1. #Гэвин Райт, спасибо за совет. Но я должен сделать это с помощью ListView(