看效果图

1、事件监听类
OnItemClickListener:3D旋转视图项点击监听器接口
public interface OnItemClickListener {
/**
* 当旋转视图中的项被点击时调用
*
* @param view 被点击的视图对象
* @param position 被点击项在旋转视图中的位置索引(从0开始)
*/
void onItemClick(View view, int position);
}
OnItemSelectedListener:3D旋转视图项选中监听器接口
public interface OnItemSelectedListener {
/**
* 当旋转视图中的选中项发生变化时调用
*
* @param item 新选中项在旋转视图中的位置索引(从0开始)
* @param view 新选中的视图对象
*/
void selected(int item, View view);
}
OnLoopViewTouchListener:3D旋转视图触摸事件监听器接口
public interface OnLoopViewTouchListener {
/**
* 当旋转视图接收到触摸事件时调用
*
* @param event 触摸事件对象,包含触摸的类型、位置等信息
*/
void onTouch(MotionEvent event);
}
2、3D水平旋转轮播控件
我这里是参考 https://github.com/yixiaolunhui/LoopRotarySwitch ,然后进行一个小改动。
LoopRotarySwitchViewHandler.java 轮播图自动滚动处理器
/**
* 轮播图自动滚动处理器
* 用于控制轮播图的自动滚动功能
* 特点:
* 1. 支持自定义滚动时间间隔
* 2. 支持开启/关闭自动滚动
* 3. 支持自定义滚动方向
*/
public abstract class LoopRotarySwitchViewHandler extends Handler {
private boolean loop = false; // 是否开启自动滚动
public long loopTime = 3000; // 滚动时间间隔(毫秒)
public static final int msgid = 1000; // 消息ID
private Message msg = createMsg(); // 创建消息对象
/**
* 构造方法
* @param time 滚动时间间隔(毫秒)
*/
public LoopRotarySwitchViewHandler(int time) {
this.loopTime = time;
}
/**
* 处理消息
* 当收到消息时,如果开启了自动滚动,则执行滚动并发送下一条消息
*/
@Override
public void handleMessage(Message msg) {
switch (msg.what = msgid) {
case msgid:
if (loop) {
doScroll(); // 执行滚动
sendMsg(); // 发送下一条消息
}
break;
}
super.handleMessage(msg);
}
/**
* 设置是否开启自动滚动
* @param loop true开启自动滚动,false关闭自动滚动
*/
public void setLoop(boolean loop) {
this.loop = loop;
if (loop) {
sendMsg(); // 开启自动滚动,发送消息
} else {
try {
removeMessages(msgid); // 关闭自动滚动,移除消息
} catch (Exception e) {
}
}
}
/**
* 发送消息
* 移除之前的消息,创建新消息并延迟发送
*/
private void sendMsg() {
try {
removeMessages(msgid); // 移除之前的消息
} catch (Exception e) {
}
msg = createMsg(); // 创建新消息
this.sendMessageDelayed(msg, loopTime); // 延迟发送消息
}
/**
* 创建消息对象
* @return 消息对象
*/
public Message createMsg() {
Message msg = new Message();
msg.what = msgid;
return msg;
}
/**
* 设置滚动时间间隔
* @param loopTime 时间间隔(毫秒)
*/
public void setLoopTime(long loopTime) {
this.loopTime = loopTime;
}
/**
* 获取滚动时间间隔
* @return 时间间隔(毫秒)
*/
public long getLoopTime() {
return loopTime;
}
/**
* 获取是否开启自动滚动
* @return true开启,false关闭
*/
public boolean isLoop() {
return loop;
}
/**
* 执行滚动
* 由子类实现具体的滚动逻辑
*/
public abstract void doScroll();
}
LoopRotarySwitchView.java 水平旋转轮播控件
/**
* 水平旋转轮播控件
* 实现了一个可以水平旋转的轮播图效果,支持自动轮播和手动滑动
* 特点:
* 1. 支持水平方向旋转
* 2. 支持自动轮播和手动滑动
* 3. 支持自定义轮播方向
* 4. 支持自定义轮播时间间隔
* 5. 支持点击事件和选择事件
*/
public class LoopRotarySwitchView extends RelativeLayout {
private final String TAG = "LoopRotarySwitchView";
private final static int LoopR = 200; // 默认半径
private final static int vertical = 0; // 竖直方向
private final static int horizontal = 1; // 水平方向
private int mOrientation = horizontal; // 当前方向,默认水平
private Context mContext; // 上下文
private ValueAnimator restAnimator = null; // 回位动画
private ValueAnimator rAnimation = null; // 半径动画
private ValueAnimator zAnimation = null; // Z轴旋转动画
private ValueAnimator xAnimation = null; // X轴旋转动画
private int loopRotationX = 0, loopRotationZ = 0; // X轴和Z轴的旋转角度
private GestureDetector mGestureDetector = null; // 手势检测器
private int selectItem = 0; // 当前选中的item
private int size = 4; // item总数
private float r = LoopR; // 当前半径
private float multiple = 2f; // 倍数
private float distance = multiple * r; // 观察距离,影响大小差异
private float angle = 0; // 当前旋转角度
private float last_angle = 0; // 上一次的角度
private boolean autoRotation = false; // 是否自动旋转
private boolean touching = false; // 是否正在触摸
private boolean isAnimating = false; // 是否正在动画中
private AutoScrollDirection autoRotatinDirection = AutoScrollDirection.left; // 自动滚动方向
private List<View> views = new ArrayList<View>(); // 子视图列表
private OnItemSelectedListener onItemSelectedListener = null; // 选择监听器
private OnLoopViewTouchListener onLoopViewTouchListener = null; // 触摸监听器
private OnItemClickListener onItemClickListener = null; // 点击监听器
private boolean isCanClickListener = true; // 是否可以点击
private float x; // 触摸的X坐标
private float limitX = 30; // 滑动阈值
float spacingFactor = 1.2f; // 设置图片之间间距系数,可以调整这个值来改变间距
private static boolean isFirstOpen = false; // 是否第一次打开这个页面
/**
* 自动滚动方向枚举
*/
public enum AutoScrollDirection {
left, right
}
/**
* 构造方法
*/
public LoopRotarySwitchView(Context context) {
this(context, null);
}
/**
* 构造方法
*/
public LoopRotarySwitchView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* 构造方法
* 初始化控件的基本属性和动画
*/
public LoopRotarySwitchView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
// 获取自定义属性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LoopRotarySwitchView);
mOrientation = typedArray.getInt(R.styleable.LoopRotarySwitchView_orientation, horizontal);
autoRotation = typedArray.getBoolean(R.styleable.LoopRotarySwitchView_autoRotation, false);
r = typedArray.getDimension(R.styleable.LoopRotarySwitchView_r, LoopR);
int direction = typedArray.getInt(R.styleable.LoopRotarySwitchView_direction, 0);
typedArray.recycle();
// 初始化手势检测器
mGestureDetector = new GestureDetector(context, getGeomeryController());
// 设置旋转方向
if (mOrientation == horizontal) {
loopRotationZ = 0;
} else {
loopRotationZ = 90;
}
// 设置自动滚动方向
if (direction == 0) {
autoRotatinDirection = AutoScrollDirection.left;
} else {
autoRotatinDirection = AutoScrollDirection.right;
}
// 启动自动滚动
loopHandler.setLoop(autoRotation);
}
/**
* handler处理
*/
@SuppressLint("HandlerLeak")
LoopRotarySwitchViewHandler loopHandler = new LoopRotarySwitchViewHandler(3000) {
@Override
public void doScroll() {
try {
if (size != 0) {//判断自动滑动从那边开始
int perAngle = 0;
switch (autoRotatinDirection) {
case left:
perAngle = 360 / size;
break;
case right:
perAngle = -360 / size;
break;
}
if (angle == 360) {
angle = 0f;
}

最低0.47元/天 解锁文章

3545

被折叠的 条评论
为什么被折叠?



