Android实现立体滚轮控件,Camera和Matrix实现真正的3D(WheelView)滚轮控件

前言:

通过Camera, Matrix 3d旋转+RecyclerView实现和(IOS时间地址选择3D)滚轮控件一样效果的WheelView,实现安卓QQ上滚轮一样的滑动效果

一:先看效果图

77656dbb07b2

垂直方向的3D旋转

77656dbb07b2

水平方向的3D旋转

二:功能分析

1:3D旋转效果

WheelView的实现方式已经有很多种方式, 而且网上也有实现好的旋转效果,不过只是2D的旋转,而且要处理滑动与单击item事件比较复杂,真正的旋转是要通过Matrix, Camera类来实现,这里的Camera不是照相机里的API,Camera可以实现x,y,z轴的旋转,不清楚的可以去也解这些API的使用, 这里不详细介绍, 配合RecyclerView.ItemDecoration,在每个item中将Canvas进行3D旋转并平移,产生3D视觉效果

这里拿垂直布局的一种状态来做示例

/**

* 画垂直布局时的item

* @param c

* @param rect

* @param position

* @param parentCenterX RecyclerView的中心X点

* @param parentCenterY RecyclerView的中心Y点

*/

void drawVerticalItem(Canvas c, Rect rect, int position, float parentCenterX, float parentCenterY) {

int realPosition = position - itemCount;//数据中的实际位置

float itemCenterY = rect.exactCenterY();

float scrollOffY = itemCenterY - parentCenterY;

float rotateDegreeX = scrollOffY * itemDegree / itemSize;//垂直布局时要以X轴为中心旋转

int alpha = degreeAlpha(rotateDegreeX);

if (alpha <= 0) return;

float rotateSinX = (float) Math.sin(Math.toRadians(rotateDegreeX));

float rotateOffY = scrollOffY - wheelRadio * rotateSinX;//因旋转导致界面视角的偏移

//Log.i("you", "drawVerticalItem degree " + rotateDegreeX);

//计算中心item, 优先最靠近中心区域的为中心点

boolean isCenterItem = false;

if (!hasCenterItem) {

isCenterItem = Math.abs(scrollOffY) <= halfItemHeight;

if (isCenterItem) {

centerItemPosition = realPosition;

hasCenterItem = true;

}

}

//这里是旋转操作的核心,每个item在旋转成弧时,都要将item的中心在旋转后给人的视觉上的偏移计算好

c.save();

c.translate(0.0f, -rotateOffY);//因旋转导致界面视角的偏移

camera.save();

//旋转时离视角的z轴方向也会变化,先移动Z轴再旋转

float z = (float) (wheelRadio * (1 - Math.abs(Math.cos(Math.toRadians(rotateDegreeX)))));

camera.translate(0, 0, z);

camera.rotateX(-rotateDegreeX);

camera.getMatrix(matrix);

camera.restore();

matrix.preTranslate(-translateX, -itemCenterY);

matrix.postTranslate(translateX, itemCenterY);

c.concat(matrix);

drawItem(c, rect, realPosition, alpha, isCenterItem, true);

c.restore();

}

到这里基本已经实现了每个item距离中心点的旋转效果,接下来就是添加WheelView显示的数量在RecyclerView头与尾部的空的item

2: 适配器定义

滑动的时候,item要能滑动距中心点以上,也可以滑动到中心点以下,所以适配器中的item数量也要对应改变,直接上代码

class WheelViewAdapter extends RecyclerView.Adapter {

...伪代码

@Override

public void onBindViewHolder(WheelViewHolder holder, int position) {

//由于里面的文本全是画的,这里只是绑定最原始的View

}

@Override

public int getItemCount() {

// 这里的totalItemCount就是滑轮控件距离中心点显示的item个数 乘2

return totalItemCount + (adapter == null ? 0 : adapter.getItemCount());

}

@Override

public WheelViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

//适配器里根据垂直或水平布局显示

View view = new View(parent.getContext());

view.setLayoutParams(WheelUtils.createLayoutParams(orientation, itemSize));

return new WheelViewHolder(view);

}

}

总结:

WheelView具体使用方法,示例代码中都有详细介绍

后面有空再加上item点击与左右偏移时的立体效果,还有封装日期选择等...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值