如何平滑列表项在特定位置的移动
How to smooth the movement of a list item at a specific position
我有列表视图。当项目处于特定位置时,他会改变颜色。 (见图)。在顶部(带有蓝色方块)-这就是我现在所拥有的。下来-我需要的。但是当滚动时,当项目在所需位置并改变颜色时,它不会顺利发生。该项目似乎跳到了所需的位置。我怎样才能使这个过程更顺利?谢谢
这是我的部分观点class:
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);
}
}
}
};
如果您改用 RecyclerView 而不是 ListView(无论如何您都应该这样做),您可以为此使用 SnapHelper
:
SnapHelper helper = new LinearSnapHelper();
helper.attachToRecyclerView(recyclerView);
试试这个:
@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);
}
}
更新:
上面的代码有一个恒定的稳定时间(500ms)。下面的代码有一个恒定的捕捉速度(0.2 pixel/ms,这意味着滚动 up/down 一个像素需要 5ms)。
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);
}
}
我有列表视图。当项目处于特定位置时,他会改变颜色。 (见图)。在顶部(带有蓝色方块)-这就是我现在所拥有的。下来-我需要的。但是当滚动时,当项目在所需位置并改变颜色时,它不会顺利发生。该项目似乎跳到了所需的位置。我怎样才能使这个过程更顺利?谢谢
这是我的部分观点class:
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);
}
}
}
};
如果您改用 RecyclerView 而不是 ListView(无论如何您都应该这样做),您可以为此使用 SnapHelper
:
SnapHelper helper = new LinearSnapHelper();
helper.attachToRecyclerView(recyclerView);
试试这个:
@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);
}
}
更新: 上面的代码有一个恒定的稳定时间(500ms)。下面的代码有一个恒定的捕捉速度(0.2 pixel/ms,这意味着滚动 up/down 一个像素需要 5ms)。
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);
}
}