一样先上最总效果图

实现的是一个弧形横向滑动的列表
实现过程:离不开的LayoutManager实现三部曲
1.继承RecyclerView.LayoutManager
2.重写onLayoutChildren来添加子View 完成一个列表的静态界面
3.重写scrollVerticallyBy来实现竖向滚动 是列表可以滚动
具体实现:
创建一个条目类
为了能使每个View都具有自己的属性 所以一样为每个条目创建自己的bean
我们先分析一下所需要的属性
public class ArcViewBean {
//距离左边的距离
private int left;
//距离下面的距离
private int bottom;
//缩放大小
private float scaleXY = 1.0f;
//旋转角度
private float rotate;
public float getScaleXY() {
if(rotate>90||rotate<-90){
return 0.5f;
}else{
return 0.5f +(90-Math.abs(rotate))/90;
}
}
}
这里面每个条目都需要四个属性来判断换显示 分别是:左边距 下边距 旋转角度 缩放并在内部定义缩放规则
实现静态界面
(1)创建所有要显示View的Bean
private ArrayList<ArcViewBean> createItemViewInfoList() {
ArrayList<ArcViewBean> arcViewBeans = new ArrayList<>();
for (int i = 0; i < getItemCount(); i++) {
ArcViewBean arcViewBean = new ArcViewBean();
float rotate = mRotate + i * intervalAngle;
arcViewBean.setRotate(rotate);
arcViewBean.setLeft(startLeft + calLeftPosition(rotate));
arcViewBean.setBottom(startBottom - calBottomPosition(rotate));
arcViewBeans.add(arcViewBean);
}
return arcViewBeans;
}
(2)移除View放入缓存中并绘制View
//在布局之前,将所有的子View先Detach掉,放入到Scrap缓存中
detachAndScrapAttachedViews(recycler);
绘制View
private void drawView(RecyclerView.Recycler recycler, RecyclerView.State state, ArrayList<ArcViewBean> arcViewBeans) {
if (state.isPreLayout()) return;
for (int i = 0; i < getItemCount(); i++) {
ArcViewBean arcViewBean = arcViewBeans.get(i);
if (arcViewBean.getRotate() <= maxRemoveDegree
&& arcViewBean.getRotate() >= minRemoveDegree) {
View scrap = recycler.getViewForPosition(i);
measureChildWithMargins(scrap, 0, 0);
addView(scrap);
int left = arcViewBean.getLeft();
int bottom = arcViewBean.getBottom();
scrap.setRotation(arcViewBean.getRotate());
layoutDecorated(scrap, left, bottom,
left + mDecoratedChildWidth, bottom + mDecoratedChildHeight);
scrap.setScaleX(arcViewBean.getScaleXY());
scrap.setScaleY(arcViewBean.getScaleXY());
}
}
}
这样就显示了静态界面
让界面可以滑动起来
因为是横向滑动
@Override
public boolean canScrollHorizontally() {
return true;
}
然后 设置一个横向滑动与角度的转换比例 DISTANCE_RATIO 让我们可以计算出滑动的角度
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
int willScroll = dx;
//每个item x方向上的移动距离
float theta = dx / DISTANCE_RATIO;
float targetRotate = offsetRotate + theta;
//目标角度
if (targetRotate < 0) {
willScroll = (int) (-offsetRotate * DISTANCE_RATIO);
} else if (targetRotate > getMaxOffsetDegree()) {
willScroll = (int) ((getMaxOffsetDegree() - offsetRotate) * DISTANCE_RATIO);
}
theta = willScroll / DISTANCE_RATIO;
//当前移动的总角度
offsetRotate += theta;
layoutChildView(recycler, state);
return willScroll;
}
计算完以后只需要子设置的时候 这样修改就可以滑动起来了
float rotate = mRotate + i * intervalAngle - offsetRotate;
demo Github地址 :https://github.com/525642022/LayoutManagerTest
网友评论