gpt4 book ai didi

android - 如何使用回收器 View 模拟 View 寻呼机?

转载 作者:行者123 更新时间:2023-12-04 11:42:12 25 4
gpt4 key购买 nike

ViewPager 优于 RecyclerView 的一个优点是它有一个 setPageTransformer() 监听器。在这里,您可以操作页面并将其转换为在滑动之间或滑动时制作整洁的动画。我想模仿在使用 RecyclerView 时能够转换页面。

首先,我使用 LinearSnapHelper 模仿 ViewPager 的行为

    LinearSnapHelper snapHelper = new LinearSnapHelper() {
@Override
public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {
View centerView = findSnapView(layoutManager);
if (centerView == null) {
return RecyclerView.NO_POSITION;
}

int position = layoutManager.getPosition(centerView);
int targetPosition = -1;
if (layoutManager.canScrollHorizontally()) {
if (velocityX < 0) {
targetPosition = position - 1;
} else {
targetPosition = position + 1;
}
}

if (layoutManager.canScrollVertically()) {
if (velocityY < 0) {
targetPosition = position - 1;
} else {
targetPosition = position + 1;
}
}

final int firstItem = 0;
final int lastItem = layoutManager.getItemCount() - 1;
targetPosition = Math.min(lastItem, Math.max(targetPosition, firstItem));
return targetPosition;
}
};
snapHelper.attachToRecyclerView(recyclerview);

这工作得很好,看起来非常好。现在我想在滑动页面(项目)时对其进行转换。使用 ViewPager,我可以使用以下代码执行此操作:
    viewpager.setPageTransformer(false, new ViewPager.PageTransformer() {
private static final float MIN_SCALE = 0.85f;

public void transformPage(@NonNull View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();

// modify the default slide transition to shrink the page
float scaleFactor = Math.max(MIN_SCALE, 1 - (Math.abs(position) / 5));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}

// scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
}
});

由于没有用于 RecyclerViews 的页面转换器监听器,我认为等价物将在 ScrollChangeListener 上。所以我将代码添加到那个监听器
    recyclerview.setOnScrollChangeListener(new View.OnScrollChangeListener() {
@Override
public void onScrollChange(View view, int i, int i1, int i2, int i3) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
// modify the default slide transition to shrink the page
float scaleFactor = Math.max(0.85f, 1 - (Math.abs(mLayoutManager.findFirstVisibleItemPosition()) / 5));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (mLayoutManager.findFirstVisibleItemPosition() < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}

// scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
}
});

页面根本没有缩放。一切似乎都被忽略了。我应该把转换代码放在哪里?当您在项目之间切换时,我希望每个项目都缩小和增长。想想 Carousal 动画,例如 https://github.com/jgabrielfreitas/android-carousel

编辑:
尝试在 onScroll 中转换 View 太难了,所以我最终修改了 LayoutManager。这很好用。我只需要弄清楚如何偷看。这是我想出的,它具有我正在寻找的轮播动画外观。
public class CustomLinearLayoutManager extends LinearLayoutManager {

private final float mShrinkAmount = 0.15f;
private final float mShrinkDistance = 1.0f;

public CustomLinearLayoutManager(Context context) {
super(context);
}

@Override
public int scrollVerticallyBy(int dy, @NonNull RecyclerView.Recycler recycler, @NonNull RecyclerView.State state) {
int orientation = getOrientation();
if (orientation == VERTICAL) {
int scrolled = super.scrollVerticallyBy(dy, recycler, state);
float midpoint = getHeight() / 2.0f;
float d0 = 0.0f;
float d1 = mShrinkDistance * midpoint;
float s0 = 1.0f;
float s1 = 1.0f - mShrinkAmount;
// loop through active children and set scale of child
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
float childMidpoint = (getDecoratedBottom(child) + getDecoratedTop(child)) / 2.0f;
float d = Math.min(d1, Math.abs(midpoint - childMidpoint));
float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0);
child.setScaleX(scale);
child.setScaleY(scale);
}
return scrolled;
} else {
return 0;
}
}

@Override
public int scrollHorizontallyBy(int dx, @NonNull RecyclerView.Recycler recycler, @NonNull RecyclerView.State state) {
int orientation = getOrientation();
if (orientation == HORIZONTAL) {
int scrolled = super.scrollHorizontallyBy(dx, recycler, state);
float midpoint = getWidth() / 2.0f;
float d0 = 0.0f;
float d1 = mShrinkDistance * midpoint;
float s0 = 1.0f;
float s1 = 1.0f - mShrinkAmount;
// loop through active children and set scale of child
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
float childMidpoint = (getDecoratedRight(child) + getDecoratedLeft(child)) / 2.0f;
float d = Math.min(d1, Math.abs(midpoint - childMidpoint));
float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0);
child.setScaleX(scale);
child.setScaleY(scale);
}
return scrolled;
} else {
return 0;
}
}

@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
scrollVerticallyBy(0, recycler, state);
}
}

最佳答案

我实现了你的(@portfoliobuilder)类,但它只向我显示垂直回收器 View ,我想要回收器 View 的水平方向,但不知何故它不模仿水平。如果我自定义您的类(class),那么它会停止模仿 viewpager2 并成为正常的回收站 View 。

public class CustomLinearLayoutManager extends LinearLayoutManager {

private final float mShrinkAmount = 0.15f;
private final float mShrinkDistance = 1.0f;

public CustomLinearLayoutManager(Context context) {
super(context);
}

@Override
public int scrollVerticallyBy(int dy, @NonNull RecyclerView.Recycler recycler, @NonNull RecyclerView.State state) {
int orientation = getOrientation();
if (orientation == VERTICAL) {
int scrolled = super.scrollVerticallyBy(dy, recycler, state);
float midpoint = getHeight() / 2.0f;
float d0 = 0.0f;
float d1 = mShrinkDistance * midpoint;
float s0 = 1.0f;
float s1 = 1.0f - mShrinkAmount;
// loop through active children and set scale of child
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
float childMidpoint = (getDecoratedBottom(child) + getDecoratedTop(child)) / 2.0f;
float d = Math.min(d1, Math.abs(midpoint - childMidpoint));
float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0);
child.setScaleX(scale);
child.setScaleY(scale);
}
return scrolled;
} else {
return 0;
}
}

@Override
public int scrollHorizontallyBy(int dx, @NonNull RecyclerView.Recycler recycler, @NonNull RecyclerView.State state) {
int orientation = getOrientation();
if (orientation == HORIZONTAL) {
int scrolled = super.scrollHorizontallyBy(dx, recycler, state);
float midpoint = getWidth() / 2.0f;
float d0 = 0.0f;
float d1 = mShrinkDistance * midpoint;
float s0 = 1.0f;
float s1 = 1.0f - mShrinkAmount;
// loop through active children and set scale of child
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
float childMidpoint = (getDecoratedRight(child) + getDecoratedLeft(child)) / 2.0f;
float d = Math.min(d1, Math.abs(midpoint - childMidpoint));
float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0);
child.setScaleX(scale);
child.setScaleY(scale);
}
return scrolled;
} else {
return 0;
}
}

@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
scrollVerticallyBy(0, recycler, state);
}
}

关于android - 如何使用回收器 View 模拟 View 寻呼机?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49884648/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com