1:修改群了会抽奖的动画
2:动画未完成
This commit is contained in:
@@ -63,7 +63,7 @@ public class AppUpdateDialog extends BaseDialog<DialogAppUpdateBinding> implemen
|
|||||||
};
|
};
|
||||||
mProgressDialog.setMax(100);//设置最大值
|
mProgressDialog.setMax(100);//设置最大值
|
||||||
mProgressDialog.setTitle("安装包下载");//设置标题
|
mProgressDialog.setTitle("安装包下载");//设置标题
|
||||||
mProgressDialog.setIcon(R.mipmap.ic_launcher);//设置标题小图标
|
mProgressDialog.setIcon(R.mipmap.ic_launcher_app);//设置标题小图标
|
||||||
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//设置样式为横向显示进度的样式
|
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//设置样式为横向显示进度的样式
|
||||||
mProgressDialog.incrementProgressBy(0);//设置初始值为0,其实可以不用设置,默认就是0
|
mProgressDialog.incrementProgressBy(0);//设置初始值为0,其实可以不用设置,默认就是0
|
||||||
mProgressDialog.setIndeterminate(false);//是否精确显示对话框,flase为是,反之为否
|
mProgressDialog.setIndeterminate(false);//是否精确显示对话框,flase为是,反之为否
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import lombok.Data;
|
|||||||
public class XlhDrawBean {
|
public class XlhDrawBean {
|
||||||
private int gift_id;
|
private int gift_id;
|
||||||
private String gift_name;
|
private String gift_name;
|
||||||
private String gift_base_image;
|
private String base_image;
|
||||||
private String gift_price;
|
private String gift_price;
|
||||||
private int count ;
|
private int count ;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class GiftItemAdapter extends BaseQuickAdapter<XlhDrawBean, BaseViewHolde
|
|||||||
protected void convert(BaseViewHolder helper, XlhDrawBean item) {
|
protected void convert(BaseViewHolder helper, XlhDrawBean item) {
|
||||||
|
|
||||||
helper.setText(R.id.tv_gift_name, item.getGift_name()+"x"+item.getCount());
|
helper.setText(R.id.tv_gift_name, item.getGift_name()+"x"+item.getCount());
|
||||||
ImageUtils.loadHeadCC(item.getGift_base_image(),helper.getView(R.id.gift_img));
|
ImageUtils.loadHeadCC(item.getBase_image(),helper.getView(R.id.gift_img));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,143 @@
|
|||||||
package com.xscm.moduleutil.dialog.giftLottery;
|
package com.xscm.moduleutil.dialog.giftLottery;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import com.chad.library.adapter.base.BaseQuickAdapter;
|
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||||
import com.chad.library.adapter.base.BaseViewHolder;
|
import com.chad.library.adapter.base.BaseViewHolder;
|
||||||
import com.xscm.moduleutil.R;
|
import com.xscm.moduleutil.R;
|
||||||
import com.xscm.moduleutil.bean.GiftBean;
|
import com.xscm.moduleutil.bean.GiftBean;
|
||||||
import com.xscm.moduleutil.utils.ImageUtils;
|
import com.xscm.moduleutil.utils.ImageUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
public class GiftXlhChouAdapter extends BaseQuickAdapter<GiftBean, BaseViewHolder> {
|
public class GiftXlhChouAdapter extends BaseQuickAdapter<GiftBean, BaseViewHolder> {
|
||||||
|
private List<GiftBean> giftLists = new ArrayList<>();
|
||||||
|
private int selectedPosition = -1;
|
||||||
|
private static final int LOOP_COUNT = 6; // 循环倍数
|
||||||
|
|
||||||
|
|
||||||
public GiftXlhChouAdapter() {
|
public GiftXlhChouAdapter() {
|
||||||
super(R.layout.item_xlh);
|
super(R.layout.item_xlh);
|
||||||
}
|
}
|
||||||
|
// 设置数据时创建循环数据
|
||||||
|
@Override
|
||||||
|
public void setNewData(List<GiftBean> data) {
|
||||||
|
this.giftLists = data != null ? data : new ArrayList<>();
|
||||||
|
super.setNewData(createLoopData());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建循环数据
|
||||||
|
* @return 循环数据列表
|
||||||
|
*/
|
||||||
|
private List<GiftBean> createLoopData() {
|
||||||
|
List<GiftBean> loopData = new ArrayList<>();
|
||||||
|
if (giftLists.isEmpty()) {
|
||||||
|
return loopData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建足够多的循环数据以实现循环效果
|
||||||
|
for (int i = 0; i < LOOP_COUNT; i++) {
|
||||||
|
loopData.addAll(giftLists);
|
||||||
|
}
|
||||||
|
return loopData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
// 如果原始数据为空,返回0
|
||||||
|
if (giftLists.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// 返回循环数据的数量
|
||||||
|
return super.getItemCount();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取实际位置(将循环位置映射到原始数据位置)
|
||||||
|
* @param position 循环列表中的位置
|
||||||
|
* @return 原始数据中的实际位置
|
||||||
|
*/
|
||||||
|
private int getActualPosition(int position) {
|
||||||
|
if (giftLists.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return position % giftLists.size();
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void convert(BaseViewHolder helper, GiftBean item) {
|
protected void convert(BaseViewHolder helper, GiftBean item) {
|
||||||
helper.setText(R.id.tv_gift_name, item.getGift_name());
|
// 获取实际位置
|
||||||
helper.setText(R.id.tv_gift_pic, item.getGift_price());
|
int actualPosition = getActualPosition(helper.getAdapterPosition());
|
||||||
ImageUtils.loadHeadCC(item.getBase_image(),helper.getView(R.id.iv_gift_image));
|
GiftBean actualItem = giftLists.get(actualPosition);
|
||||||
|
|
||||||
|
helper.setText(R.id.tv_gift_name, actualItem.getGift_name());
|
||||||
|
helper.setText(R.id.tv_gift_pic, actualItem.getGift_price());
|
||||||
|
ImageUtils.loadHeadCC(actualItem.getBase_image(), helper.getView(R.id.iv_gift_image));
|
||||||
|
// 处理选中状态
|
||||||
|
View selectedIcon = helper.getView(R.id.selected_icon);
|
||||||
|
// 处理选中状态
|
||||||
|
if (selectedIcon != null) {
|
||||||
|
// 检查当前item是否为选中位置
|
||||||
|
if (actualPosition == selectedPosition) {
|
||||||
|
selectedIcon.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
selectedIcon.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 设置选中位置并更新UI
|
||||||
|
* @param position 选中的位置
|
||||||
|
*/
|
||||||
|
public void setSelectedPosition(int position) {
|
||||||
|
int previousPosition = selectedPosition;
|
||||||
|
selectedPosition = position;
|
||||||
|
|
||||||
|
if (previousPosition >= 0) {
|
||||||
|
notifyItemsByActualPosition(previousPosition, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedPosition >= 0) {
|
||||||
|
notifyItemsByActualPosition(selectedPosition, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 根据实际位置通知所有匹配的item更新
|
||||||
|
* @param actualPosition 原始数据中的位置
|
||||||
|
* @param isSelected 是否选中
|
||||||
|
*/
|
||||||
|
private void notifyItemsByActualPosition(int actualPosition, boolean isSelected) {
|
||||||
|
if (giftLists.isEmpty() || actualPosition >= giftLists.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通知所有匹配该实际位置的item更新
|
||||||
|
for (int i = 0; i < getItemCount(); i++) {
|
||||||
|
if (getActualPosition(i) == actualPosition) {
|
||||||
|
notifyItemChanged(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 清除选中状态
|
||||||
|
*/
|
||||||
|
public void clearSelection() {
|
||||||
|
int previousPosition = selectedPosition;
|
||||||
|
selectedPosition = -1;
|
||||||
|
|
||||||
|
if (previousPosition >= 0) {
|
||||||
|
notifyItemsByActualPosition(previousPosition, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取原始数据大小
|
||||||
|
* @return 原始数据大小
|
||||||
|
*/
|
||||||
|
public int getOriginalDataSize() {
|
||||||
|
return giftLists.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.LinearSnapHelper;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.blankj.utilcode.util.TimeUtils;
|
import com.blankj.utilcode.util.TimeUtils;
|
||||||
import com.xscm.moduleutil.R;
|
import com.xscm.moduleutil.R;
|
||||||
@@ -26,6 +28,8 @@ import com.xscm.moduleutil.bean.blindboxwheel.XlhDrawBean;
|
|||||||
import com.xscm.moduleutil.databinding.FragmentTourClubDialogBinding;
|
import com.xscm.moduleutil.databinding.FragmentTourClubDialogBinding;
|
||||||
import com.xscm.moduleutil.dialog.WebViewDialog;
|
import com.xscm.moduleutil.dialog.WebViewDialog;
|
||||||
import com.xscm.moduleutil.utils.ImageUtils;
|
import com.xscm.moduleutil.utils.ImageUtils;
|
||||||
|
import com.xscm.moduleutil.widget.CenterScrollHelper;
|
||||||
|
import com.xscm.moduleutil.widget.EqualSpaceItemDecoration;
|
||||||
import com.xscm.moduleutil.widget.InfintLinearLayoutManager;
|
import com.xscm.moduleutil.widget.InfintLinearLayoutManager;
|
||||||
import com.xscm.moduleutil.widget.pagerecyclerview.PagerGridSnapHelper;
|
import com.xscm.moduleutil.widget.pagerecyclerview.PagerGridSnapHelper;
|
||||||
|
|
||||||
@@ -47,6 +51,10 @@ public class TourClubDialogFragment extends BaseMvpDialogFragment<GiftLotteryPre
|
|||||||
private XlhRecordDialog xlhRecordDialog;
|
private XlhRecordDialog xlhRecordDialog;
|
||||||
|
|
||||||
private GiftXlhChouAdapter giftXlhChouAdapter;
|
private GiftXlhChouAdapter giftXlhChouAdapter;
|
||||||
|
private CenterScrollHelper scrollHelper;
|
||||||
|
|
||||||
|
private static final int ITEM_COUNT = 24;
|
||||||
|
private static final int ROTATION_COUNT = 3;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected GiftLotteryPresenter bindPresenter() {
|
protected GiftLotteryPresenter bindPresenter() {
|
||||||
@@ -121,14 +129,31 @@ public class TourClubDialogFragment extends BaseMvpDialogFragment<GiftLotteryPre
|
|||||||
mBinding.tvJl.setOnClickListener(this::onClick);
|
mBinding.tvJl.setOnClickListener(this::onClick);
|
||||||
|
|
||||||
giftXlhChouAdapter=new GiftXlhChouAdapter();
|
giftXlhChouAdapter=new GiftXlhChouAdapter();
|
||||||
GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 3);
|
// 使用 LinearLayoutManager 横向滚动
|
||||||
|
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
|
||||||
mBinding.recycleView.setLayoutManager(new InfintLinearLayoutManager(mBinding.recycleView));
|
mBinding.recycleView.setLayoutManager(layoutManager);
|
||||||
mBinding.recycleView.setOnFlingListener(null);
|
mBinding.recycleView.setOnFlingListener(null);
|
||||||
|
|
||||||
// 设置滚动辅助工具
|
// 设置滚动辅助工具
|
||||||
PagerGridSnapHelper pageSnapHelper = new PagerGridSnapHelper();
|
LinearSnapHelper snapHelper = new LinearSnapHelper();
|
||||||
pageSnapHelper.attachToRecyclerView(mBinding.recycleView);
|
snapHelper.attachToRecyclerView(mBinding.recycleView);
|
||||||
|
|
||||||
|
// 添加 ItemDecoration 实现等宽分布
|
||||||
|
int spacing = getResources().getDimensionPixelSize(R.dimen.dp_15); // 根据需要调整间距
|
||||||
|
mBinding.recycleView.addItemDecoration(new EqualSpaceItemDecoration(3, spacing));
|
||||||
|
|
||||||
mBinding.recycleView.setAdapter(giftXlhChouAdapter);
|
mBinding.recycleView.setAdapter(giftXlhChouAdapter);
|
||||||
|
// 初始化滚动帮助类
|
||||||
|
scrollHelper = new CenterScrollHelper(mBinding.recycleView);
|
||||||
|
|
||||||
|
// 初始化时滚动到中间位置,确保有足够的前后数据
|
||||||
|
mBinding.recycleView.post(() -> {
|
||||||
|
if (giftXlhChouAdapter.getOriginalDataSize() > 0) {
|
||||||
|
int middlePosition = giftXlhChouAdapter.getItemCount() / 2;
|
||||||
|
mBinding.recycleView.scrollToPosition(middlePosition);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +215,8 @@ public class TourClubDialogFragment extends BaseMvpDialogFragment<GiftLotteryPre
|
|||||||
getRule_url=blindBoxBean.getRule_url();
|
getRule_url=blindBoxBean.getRule_url();
|
||||||
upTitle(blindBoxBean.getBox_price());
|
upTitle(blindBoxBean.getBox_price());
|
||||||
giftLists = blindBoxBean.getGift_list();
|
giftLists = blindBoxBean.getGift_list();
|
||||||
|
// 初始滚动到中间位置,避免边界问题
|
||||||
|
// mBinding.recycleView.scrollToPosition(Integer.MAX_VALUE / 2 - (Integer.MAX_VALUE / 2) % giftLists.size());
|
||||||
|
|
||||||
// 获取结束时间并启动倒计时
|
// 获取结束时间并启动倒计时
|
||||||
if (blindBoxBean.getXlh_end_time() != null && !blindBoxBean.getXlh_end_time().isEmpty()) {
|
if (blindBoxBean.getXlh_end_time() != null && !blindBoxBean.getXlh_end_time().isEmpty()) {
|
||||||
@@ -228,7 +255,7 @@ public class TourClubDialogFragment extends BaseMvpDialogFragment<GiftLotteryPre
|
|||||||
private void upTitle(int boxPrice){
|
private void upTitle(int boxPrice){
|
||||||
mBinding.tvOne.setText(boxPrice+"币一次");
|
mBinding.tvOne.setText(boxPrice+"币一次");
|
||||||
mBinding.tvTen.setText((boxPrice*10)+"币十次");
|
mBinding.tvTen.setText((boxPrice*10)+"币十次");
|
||||||
mBinding.tvHundred.setText((boxPrice*100)+"币十次");
|
mBinding.tvHundred.setText((boxPrice*100)+"币百次");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 2025/8/29 接收im推送过来的消息
|
// TODO: 2025/8/29 接收im推送过来的消息
|
||||||
@@ -357,27 +384,367 @@ public class TourClubDialogFragment extends BaseMvpDialogFragment<GiftLotteryPre
|
|||||||
@Override
|
@Override
|
||||||
public void xlhChouSuccess(List<XlhDrawBean> data) {
|
public void xlhChouSuccess(List<XlhDrawBean> data) {
|
||||||
if (data != null){
|
if (data != null){
|
||||||
// 创建并显示对话框
|
// 抽奖完成后执行动画滚动
|
||||||
XlhObtainDialog dialog = new XlhObtainDialog(getActivity());
|
mBinding.recycleView.postDelayed(() -> {
|
||||||
dialog.setOnGiftItemClickListener(new XlhObtainDialog.OnGiftItemClickListener() {
|
int winningPosition = findHighestValueWinningPosition(data);
|
||||||
|
if (winningPosition != -1) {
|
||||||
|
|
||||||
@Override
|
startLotteryAnimation(winningPosition);
|
||||||
public void onPlayAgainClick() {
|
|
||||||
// 处理再玩一次点击事件
|
|
||||||
MvpPre.xlhChou(roomId,num);
|
/**
|
||||||
|
|
||||||
|
|
||||||
|
// 计算在循环列表中的目标位置(滚动几圈后停在目标位置)
|
||||||
|
int loopCount = 4; // 滚动3圈
|
||||||
|
int originalSize = giftXlhChouAdapter.getOriginalDataSize();
|
||||||
|
// 计算目标在循环列表中的位置(确保在中间区域)
|
||||||
|
|
||||||
|
int middleBaseIndex = (loopCount * originalSize) + (originalSize / 2);
|
||||||
|
int targetLoopIndex = middleBaseIndex + (winningPosition % originalSize);
|
||||||
|
|
||||||
|
// 使用scrollWithCircles方法执行带动画的滚动(带完成回调)
|
||||||
|
scrollHelper.scrollWithCircles(
|
||||||
|
targetLoopIndex, // 在循环列表中的位置
|
||||||
|
loopCount, // 滚动圈数
|
||||||
|
500, // 每个item滚动时间200ms(控制速度)
|
||||||
|
originalSize, // 原始数据大小
|
||||||
|
() -> { // 滚动完成回调
|
||||||
|
// 滚动完成后更新选中状态(使用原始位置)
|
||||||
|
if (giftXlhChouAdapter != null) {
|
||||||
|
giftXlhChouAdapter.setSelectedPosition(winningPosition);
|
||||||
|
}
|
||||||
|
// 滚动完成后延迟一小段时间再居中,确保UI更新完成
|
||||||
|
mBinding.recycleView.postDelayed(() -> {
|
||||||
|
// 手动将选中项居中
|
||||||
|
centerSelectedItem(winningPosition, originalSize);
|
||||||
|
|
||||||
|
// 显示结果对话框
|
||||||
|
getActivity().runOnUiThread(() -> {
|
||||||
|
showResultDialog(data);
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
// 在滚动完成后再显示对话框
|
||||||
|
// getActivity().runOnUiThread(() -> {
|
||||||
|
// showResultDialog(data);
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
// 如果没有找到中奖位置,直接显示对话框
|
||||||
|
showResultDialog(data);
|
||||||
}
|
}
|
||||||
|
}, 300);
|
||||||
@Override
|
|
||||||
public void onCloseClick() {
|
|
||||||
// 处理关闭点击事件
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dialog.show();
|
|
||||||
dialog.setGiftList(data);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
MvpPre.wallet();
|
MvpPre.wallet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startLotteryAnimation(int targetIndex) {
|
||||||
|
// 确保适配器有数据
|
||||||
|
if (giftXlhChouAdapter == null || giftXlhChouAdapter.getOriginalDataSize() <= 0) {
|
||||||
|
showResultDialogWithoutAnimation(targetIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinearLayoutManager layoutManager = (LinearLayoutManager) mBinding.recycleView.getLayoutManager();
|
||||||
|
if (layoutManager == null) {
|
||||||
|
showResultDialogWithoutAnimation(targetIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前第一个可见的item位置
|
||||||
|
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
|
||||||
|
if (firstVisiblePosition == RecyclerView.NO_POSITION) {
|
||||||
|
firstVisiblePosition = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前在原始数据中的实际位置
|
||||||
|
int currentActualPosition = firstVisiblePosition % giftXlhChouAdapter.getOriginalDataSize();
|
||||||
|
|
||||||
|
// 计算需要滚动的总item数
|
||||||
|
// 滚动指定圈数 + 从当前位置到目标位置的距离
|
||||||
|
int itemsToScroll = ROTATION_COUNT * giftXlhChouAdapter.getOriginalDataSize()
|
||||||
|
+ (targetIndex - currentActualPosition + giftXlhChouAdapter.getOriginalDataSize())
|
||||||
|
% giftXlhChouAdapter.getOriginalDataSize();
|
||||||
|
|
||||||
|
// 计算目标位置
|
||||||
|
int targetPosition = firstVisiblePosition + itemsToScroll;
|
||||||
|
|
||||||
|
// 确保目标位置在合理范围内
|
||||||
|
int maxPosition = giftXlhChouAdapter.getItemCount() - 1;
|
||||||
|
if (targetPosition > maxPosition) {
|
||||||
|
targetPosition = maxPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保目标位置有效
|
||||||
|
if (targetPosition >= 0) {
|
||||||
|
try {
|
||||||
|
SmoothScroller smoothScroller = new SmoothScroller(getActivity(), targetPosition);
|
||||||
|
layoutManager.startSmoothScroll(smoothScroller);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// 如果仍然出现异常,使用备选方案
|
||||||
|
showResultDialogWithoutAnimation(targetIndex);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showResultDialogWithoutAnimation(targetIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void showResultDialogWithoutAnimation(int targetIndex) {
|
||||||
|
// 直接设置选中状态
|
||||||
|
if (giftXlhChouAdapter != null) {
|
||||||
|
giftXlhChouAdapter.setSelectedPosition(targetIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 延迟显示结果对话框
|
||||||
|
mBinding.recycleView.postDelayed(() -> {
|
||||||
|
// 创建假的XlhDrawBean数据用于显示结果
|
||||||
|
List<XlhDrawBean> fakeData = new ArrayList<>();
|
||||||
|
// 这里根据需要构造假数据
|
||||||
|
showResultDialog(fakeData);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class SmoothScroller extends androidx.recyclerview.widget.LinearSmoothScroller {
|
||||||
|
|
||||||
|
private int targetPosition;
|
||||||
|
|
||||||
|
public SmoothScroller(android.content.Context context, int targetPosition) {
|
||||||
|
super(context);
|
||||||
|
this.targetPosition = targetPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int calculateTimeForScrolling(int dx) {
|
||||||
|
// 自定义滚动时间,实现速度变化
|
||||||
|
float distance = Math.abs(dx);
|
||||||
|
float speed = 1f;
|
||||||
|
if (distance < 100) {
|
||||||
|
speed = 0.3f; // 慢
|
||||||
|
} else if (distance < 300) {
|
||||||
|
speed = 1f; // 快
|
||||||
|
} else {
|
||||||
|
speed = 0.3f; // 慢
|
||||||
|
}
|
||||||
|
return (int) (distance / speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
|
||||||
|
// 将目标项移动到屏幕中心
|
||||||
|
return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTargetPosition() {
|
||||||
|
// 添加更严格的边界检查
|
||||||
|
if (giftXlhChouAdapter != null && targetPosition >= 0 && targetPosition < giftXlhChouAdapter.getItemCount()) {
|
||||||
|
return targetPosition;
|
||||||
|
}
|
||||||
|
// 如果超出范围,返回一个安全的位置
|
||||||
|
if (giftXlhChouAdapter != null && giftXlhChouAdapter.getItemCount() > 0) {
|
||||||
|
return Math.max(0, Math.min(targetPosition, giftXlhChouAdapter.getItemCount() - 1));
|
||||||
|
}
|
||||||
|
return 0; // 返回默认位置
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将指定的原始位置item居中显示
|
||||||
|
* @param originalPosition 原始数据中的位置
|
||||||
|
* @param originalSize 原始数据大小
|
||||||
|
*/
|
||||||
|
private void centerSelectedItem(int originalPosition, int originalSize) {
|
||||||
|
LinearLayoutManager layoutManager = (LinearLayoutManager) mBinding.recycleView.getLayoutManager();
|
||||||
|
if (layoutManager == null) return;
|
||||||
|
|
||||||
|
// 计算出需要滚动到的目标位置
|
||||||
|
int targetPosition = originalPosition + 4 * originalSize;
|
||||||
|
|
||||||
|
// 使用smoothScrollToPosition滚动到目标位置
|
||||||
|
mBinding.recycleView.smoothScrollToPosition(targetPosition);
|
||||||
|
|
||||||
|
// 等待滚动完成
|
||||||
|
mBinding.recycleView.postDelayed(() -> {
|
||||||
|
// 计算出选中项的偏移量,确保它在中间
|
||||||
|
View view = layoutManager.findViewByPosition(targetPosition);
|
||||||
|
if (view == null) return;
|
||||||
|
|
||||||
|
// 计算出RecyclerView的宽度和View的宽度
|
||||||
|
int recyclerViewWidth = mBinding.recycleView.getWidth();
|
||||||
|
int viewWidth = view.getWidth();
|
||||||
|
|
||||||
|
// 计算偏移量,确保view居中
|
||||||
|
int offsetToCenter = (recyclerViewWidth / 2) - (viewWidth / 2) - view.getLeft();
|
||||||
|
|
||||||
|
// 调整滚动的位置
|
||||||
|
mBinding.recycleView.scrollBy(offsetToCenter, 0);
|
||||||
|
}, 500); // 500毫秒的延迟,根据实际情况调整
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接滚动到指定位置并居中
|
||||||
|
* @param targetPosition 目标位置
|
||||||
|
*/
|
||||||
|
private void directScrollToCenter(int targetPosition) {
|
||||||
|
if (mBinding.recycleView.getLayoutManager() == null) return;
|
||||||
|
|
||||||
|
mBinding.recycleView.post(() -> {
|
||||||
|
int screenWidth = mBinding.recycleView.getWidth();
|
||||||
|
if (screenWidth <= 0) return;
|
||||||
|
|
||||||
|
// 计算item宽度
|
||||||
|
int itemWidth = screenWidth / 3;
|
||||||
|
|
||||||
|
// 计算目标位置的左边缘
|
||||||
|
int targetLeft = targetPosition * itemWidth;
|
||||||
|
|
||||||
|
// 计算使item居中需要滚动到的位置
|
||||||
|
int targetScrollX = targetLeft - (screenWidth - itemWidth) / 2;
|
||||||
|
|
||||||
|
// 直接滚动到目标位置
|
||||||
|
mBinding.recycleView.scrollBy(
|
||||||
|
targetScrollX - mBinding.recycleView.computeHorizontalScrollOffset(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 滚动到指定位置并使该位置的item居中显示
|
||||||
|
* @param selectedPosition 选中的原始位置
|
||||||
|
*/
|
||||||
|
private void scrollToCenterWithSelected(int selectedPosition) {
|
||||||
|
if (mBinding.recycleView.getLayoutManager() == null) return;
|
||||||
|
|
||||||
|
int screenWidth = mBinding.recycleView.getWidth();
|
||||||
|
if (screenWidth <= 0) return;
|
||||||
|
|
||||||
|
// 计算item宽度
|
||||||
|
int itemWidth = screenWidth / 3;
|
||||||
|
|
||||||
|
// 计算要滚动到的中心位置(使selectedPosition的item居中)
|
||||||
|
int middlePositionInLoop = (giftXlhChouAdapter.getItemCount() / 2 / giftXlhChouAdapter.getOriginalDataSize())
|
||||||
|
* giftXlhChouAdapter.getOriginalDataSize() + selectedPosition;
|
||||||
|
|
||||||
|
// 滚动到目标位置
|
||||||
|
mBinding.recycleView.smoothScrollToPosition(middlePositionInLoop);
|
||||||
|
|
||||||
|
// 额外确保居中
|
||||||
|
mBinding.recycleView.postDelayed(() -> {
|
||||||
|
if (scrollHelper != null) {
|
||||||
|
scrollHelper.scrollToCenter(middlePositionInLoop);
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示抽奖结果对话框
|
||||||
|
* @param data 中奖数据
|
||||||
|
*/
|
||||||
|
private void showResultDialog(List<XlhDrawBean> data) {
|
||||||
|
// 创建并显示对话框
|
||||||
|
XlhObtainDialog dialog = new XlhObtainDialog(getActivity());
|
||||||
|
dialog.setOnGiftItemClickListener(new XlhObtainDialog.OnGiftItemClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayAgainClick() {
|
||||||
|
// 处理再玩一次点击事件
|
||||||
|
MvpPre.xlhChou(roomId, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCloseClick() {
|
||||||
|
// 处理关闭点击事件
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
dialog.setGiftList(data);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 根据中奖结果找到最高价值奖品在giftLists中的位置
|
||||||
|
* @param data 中奖结果列表
|
||||||
|
* @return 最高价值奖品在giftLists中的下标,如果没有找到则返回-1
|
||||||
|
*/
|
||||||
|
private int findHighestValueWinningPosition(List<XlhDrawBean> data) {
|
||||||
|
if (data == null || data.isEmpty() || giftLists == null || giftLists.isEmpty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int targetPosition = -1;
|
||||||
|
int highestPrice = -1;
|
||||||
|
|
||||||
|
// 遍历giftLists查找中奖项目
|
||||||
|
for (int i = 0; i < giftLists.size(); i++) {
|
||||||
|
GiftBean giftBean = giftLists.get(i);
|
||||||
|
|
||||||
|
// 在中奖数据中查找匹配的礼品
|
||||||
|
for (XlhDrawBean xlhDrawBean : data) {
|
||||||
|
// 比较gift_id是否匹配
|
||||||
|
if (giftBean.getGift_id().equals(String.valueOf(xlhDrawBean.getGift_id()))) {
|
||||||
|
// 解析价格,处理可能的NumberFormatException
|
||||||
|
try {
|
||||||
|
int currentPrice = Integer.parseInt(giftBean.getGift_price());
|
||||||
|
// 如果当前价格更高,则更新目标位置和最高价格
|
||||||
|
if (currentPrice > highestPrice) {
|
||||||
|
highestPrice = currentPrice;
|
||||||
|
targetPosition = i;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// 如果价格解析失败,使用默认值0进行比较
|
||||||
|
if (highestPrice <= 0) {
|
||||||
|
highestPrice = 0;
|
||||||
|
targetPosition = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; // 找到匹配项后跳出内层循环
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 精确将指定位置的item滚动到中心
|
||||||
|
* @param position 目标位置
|
||||||
|
*/
|
||||||
|
private void preciseScrollToCenter(int position) {
|
||||||
|
if (mBinding.recycleView.getLayoutManager() == null) return;
|
||||||
|
|
||||||
|
int screenWidth = mBinding.recycleView.getWidth();
|
||||||
|
if (screenWidth <= 0) return;
|
||||||
|
|
||||||
|
// 计算item宽度
|
||||||
|
int itemWidth = screenWidth / 3;
|
||||||
|
|
||||||
|
// 计算屏幕中心位置
|
||||||
|
int screenCenter = screenWidth / 2;
|
||||||
|
|
||||||
|
// 计算目标item的中心位置(在当前可见区域中)
|
||||||
|
int targetItemCenter = (mBinding.recycleView.computeHorizontalScrollOffset() / itemWidth) * itemWidth
|
||||||
|
+ position * itemWidth + itemWidth / 2;
|
||||||
|
|
||||||
|
// 计算需要滚动的距离使目标item居中
|
||||||
|
int scrollDistance = targetItemCenter - screenCenter;
|
||||||
|
|
||||||
|
// 获取当前滚动位置
|
||||||
|
int currentScrollX = mBinding.recycleView.computeHorizontalScrollOffset();
|
||||||
|
|
||||||
|
// 执行滚动使选中项居中
|
||||||
|
mBinding.recycleView.smoothScrollBy(scrollDistance - currentScrollX, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,255 @@
|
|||||||
|
package com.xscm.moduleutil.widget;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.LinearSmoothScroller;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author lxj$
|
||||||
|
* @Time $ 2025-9-4 21:04:34$
|
||||||
|
* @Description 自定义滚动辅助类$
|
||||||
|
*/
|
||||||
|
public class CenterScrollHelper {
|
||||||
|
private RecyclerView recyclerView;
|
||||||
|
|
||||||
|
public CenterScrollHelper(RecyclerView recyclerView) {
|
||||||
|
this.recyclerView = recyclerView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 循环滚动指定圈数后停在目标位置
|
||||||
|
* @param targetPosition 目标位置
|
||||||
|
* @param circles 滚动圈数
|
||||||
|
* @param durationPerItem 每个item滚动的持续时间(控制速度)
|
||||||
|
* @param adapterSize 适配器总大小
|
||||||
|
*/
|
||||||
|
public void scrollWithCircles(int targetPosition, int circles, int durationPerItem, int adapterSize) {
|
||||||
|
scrollWithCircles(targetPosition, circles, durationPerItem, adapterSize, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 循环滚动指定圈数后停在目标位置(带回调)
|
||||||
|
* @param targetPosition 目标位置
|
||||||
|
* @param circles 滚动圈数
|
||||||
|
* @param durationPerItem 每个item滚动的持续时间(控制速度)
|
||||||
|
* @param adapterSize 适配器总大小
|
||||||
|
* @param onComplete 滚动完成回调
|
||||||
|
*/
|
||||||
|
public void scrollWithCircles(int targetPosition, int circles, int durationPerItem,
|
||||||
|
int adapterSize, Runnable onComplete) {
|
||||||
|
if (recyclerView.getLayoutManager() == null) {
|
||||||
|
if (onComplete != null) onComplete.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算总滚动位置(多圈+目标位置)
|
||||||
|
int totalItems = circles * adapterSize + targetPosition;
|
||||||
|
|
||||||
|
|
||||||
|
// 使用LinearSmoothScroller进行平滑滚动
|
||||||
|
LinearSmoothScroller smoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
|
||||||
|
@Override
|
||||||
|
protected int calculateTimeForScrolling(int dx) {
|
||||||
|
// 使用缓动函数计算时间,实现从慢到快再到慢的效果
|
||||||
|
// return calculateEasingTime(dx, durationPerItem);
|
||||||
|
|
||||||
|
// 简单线性时间计算,确保滚动速度一致
|
||||||
|
int screenWidth = recyclerView.getWidth();
|
||||||
|
if (screenWidth <= 0) {
|
||||||
|
return durationPerItem * 3;
|
||||||
|
}
|
||||||
|
int itemWidth = screenWidth / 3;
|
||||||
|
int items = Math.max(1, dx / itemWidth);
|
||||||
|
return durationPerItem * items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
// 滚动停止后确保目标位置居中
|
||||||
|
// scrollToCenter(targetPosition);
|
||||||
|
// 执行完成回调
|
||||||
|
if (onComplete != null) {
|
||||||
|
recyclerView.post(onComplete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
smoothScroller.setTargetPosition(totalItems);
|
||||||
|
recyclerView.getLayoutManager().startSmoothScroll(smoothScroller);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 使用缓动函数计算滚动时间,实现加速减速效果
|
||||||
|
* @param dx 滚动距离
|
||||||
|
* @param baseDurationPerItem 基础时间
|
||||||
|
* @return 计算后的时间
|
||||||
|
*/
|
||||||
|
private int calculateEasingTime(int dx, int baseDurationPerItem) {
|
||||||
|
if (dx <= 0) return 0;
|
||||||
|
|
||||||
|
// 获取屏幕宽度作为参考
|
||||||
|
int screenWidth = recyclerView.getWidth();
|
||||||
|
if (screenWidth <= 0) {
|
||||||
|
return baseDurationPerItem * 3; // 默认值
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算item宽度(假设每屏3个item)
|
||||||
|
int itemWidth = screenWidth / 3;
|
||||||
|
// 计算滚动的item数量
|
||||||
|
int items = Math.max(1, dx / itemWidth);
|
||||||
|
|
||||||
|
// 使用easeInOutQuad缓动函数实现先慢中快后慢的效果
|
||||||
|
double progress = Math.min(1.0, (double) items / 100); // 假设100个item为完整过程
|
||||||
|
|
||||||
|
// easeInOutQuad缓动函数
|
||||||
|
double easeProgress;
|
||||||
|
if (progress < 0.5) {
|
||||||
|
easeProgress = 2 * progress * progress; // 先慢后快
|
||||||
|
} else {
|
||||||
|
easeProgress = 1 - Math.pow(-2 * progress + 2, 2) / 2; // 后慢
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算时间:开始慢(500ms),后来快(50ms)
|
||||||
|
int minDuration = 50; // 最快速度
|
||||||
|
int maxDuration = 500; // 最慢速度
|
||||||
|
int calculatedTime = (int) (maxDuration - (maxDuration - minDuration) * easeProgress);
|
||||||
|
|
||||||
|
return Math.max(minDuration, calculatedTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将指定位置的item精确居中显示
|
||||||
|
* @param position 需要居中的位置(在循环列表中的实际位置)
|
||||||
|
* @param originalSize 原始数据大小
|
||||||
|
*/
|
||||||
|
public void scrollToCenter(int position, int originalSize) {
|
||||||
|
if (recyclerView.getLayoutManager() == null) return;
|
||||||
|
|
||||||
|
int screenWidth = recyclerView.getWidth();
|
||||||
|
if (screenWidth <= 0) return;
|
||||||
|
|
||||||
|
// 计算item宽度(假设每个item等宽)
|
||||||
|
int itemWidth = screenWidth / 3; // 每屏显示3个item
|
||||||
|
|
||||||
|
// 计算使item居中需要滚动的总距离
|
||||||
|
int targetScrollX = position * itemWidth - (screenWidth - itemWidth) / 2;
|
||||||
|
|
||||||
|
// 获取当前滚动位置
|
||||||
|
int currentScrollX = recyclerView.computeHorizontalScrollOffset();
|
||||||
|
|
||||||
|
// 计算需要滚动的距离
|
||||||
|
int scrollDistance = targetScrollX - currentScrollX;
|
||||||
|
|
||||||
|
// 执行滚动
|
||||||
|
recyclerView.smoothScrollBy(scrollDistance, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将指定位置的item精确居中显示(简化版)
|
||||||
|
* @param position 需要居中的位置
|
||||||
|
*/
|
||||||
|
public void scrollToCenter(int position) {
|
||||||
|
if (recyclerView.getLayoutManager() == null) return;
|
||||||
|
|
||||||
|
int screenWidth = recyclerView.getWidth();
|
||||||
|
if (screenWidth <= 0) return;
|
||||||
|
|
||||||
|
// 计算item宽度
|
||||||
|
int itemWidth = screenWidth / 3;
|
||||||
|
|
||||||
|
// 计算目标位置的左边缘
|
||||||
|
int targetLeft = position * itemWidth;
|
||||||
|
|
||||||
|
// 计算使item居中需要滚动到的位置
|
||||||
|
int targetScrollX = targetLeft - (screenWidth - itemWidth) / 2;
|
||||||
|
|
||||||
|
// 获取当前滚动位置
|
||||||
|
int currentScrollX = recyclerView.computeHorizontalScrollOffset();
|
||||||
|
|
||||||
|
// 计算需要滚动的距离
|
||||||
|
int scrollDistance = targetScrollX - currentScrollX;
|
||||||
|
|
||||||
|
// 如果距离很小,就不需要滚动了
|
||||||
|
if (Math.abs(scrollDistance) > 5) {
|
||||||
|
// 执行滚动
|
||||||
|
recyclerView.smoothScrollBy(scrollDistance, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 将指定位置的item居中显示(支持循环)
|
||||||
|
*/
|
||||||
|
public void centerItem(int targetPosition, int adapterSize) {
|
||||||
|
if (recyclerView.getLayoutManager() == null) return;
|
||||||
|
|
||||||
|
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||||
|
int screenWidth = recyclerView.getWidth();
|
||||||
|
if (screenWidth <= 0) return;
|
||||||
|
|
||||||
|
int itemWidth = screenWidth / 3; // 每个item占屏幕1/3
|
||||||
|
|
||||||
|
// 计算需要滚动的距离使item居中
|
||||||
|
// 这里需要根据实际的item宽度和屏幕宽度来计算居中位置
|
||||||
|
int targetScrollX = targetPosition * itemWidth - (screenWidth - itemWidth) / 2;
|
||||||
|
int currentScrollX = recyclerView.computeHorizontalScrollOffset();
|
||||||
|
int scrollDistance = targetScrollX - currentScrollX;
|
||||||
|
|
||||||
|
// 使用smoothScrollBy确保平滑滚动到居中位置
|
||||||
|
recyclerView.smoothScrollBy(scrollDistance, 0);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 使用更复杂的缓动函数计算滚动时间
|
||||||
|
* @param dx 滚动距离
|
||||||
|
* @param baseDurationPerItem 基础时间
|
||||||
|
* @return 计算后的时间
|
||||||
|
*/
|
||||||
|
private int calculateAdvancedEasingTime(int dx, int baseDurationPerItem) {
|
||||||
|
if (dx <= 0) return 0;
|
||||||
|
|
||||||
|
int screenWidth = recyclerView.getWidth();
|
||||||
|
if (screenWidth <= 0) {
|
||||||
|
return baseDurationPerItem * 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int itemWidth = screenWidth / 3;
|
||||||
|
int totalItems = dx / itemWidth;
|
||||||
|
|
||||||
|
// 分段处理:开始慢,中间快,结束慢
|
||||||
|
int totalTime = 0;
|
||||||
|
for (int i = 0; i < totalItems; i++) {
|
||||||
|
// 计算当前位置的进度 (0-1)
|
||||||
|
double progress = (double) i / Math.max(1, totalItems);
|
||||||
|
|
||||||
|
// 使用贝塞尔缓动函数:慢-快-慢
|
||||||
|
double easedProgress = bezierEasing(progress, 0.25, 0.1, 0.25, 1.0);
|
||||||
|
|
||||||
|
// 根据进度调整时间
|
||||||
|
int minTime = 30; // 最快时间
|
||||||
|
int maxTime = baseDurationPerItem * 2; // 最慢时间
|
||||||
|
int itemTime = (int) (maxTime - (maxTime - minTime) * easedProgress);
|
||||||
|
|
||||||
|
totalTime += itemTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(100, totalTime); // 至少100ms
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 贝塞尔缓动函数
|
||||||
|
* @param t 时间进度 (0-1)
|
||||||
|
* @param x1 控制点1 x
|
||||||
|
* @param y1 控制点1 y
|
||||||
|
* @param x2 控制点2 x
|
||||||
|
* @param y2 控制点2 y
|
||||||
|
* @return 缓动后的值
|
||||||
|
*/
|
||||||
|
private double bezierEasing(double t, double x1, double y1, double x2, double y2) {
|
||||||
|
// 简化的贝塞尔曲线计算
|
||||||
|
// 这里使用一个近似算法
|
||||||
|
double a = 1 - t;
|
||||||
|
return 3 * a * a * t * y1 + 3 * a * t * t * y2 + t * t * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.xscm.moduleutil.widget;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author lxj$
|
||||||
|
* @Time $ 2025-9-4 20:32:52$
|
||||||
|
* @Description 自定义的,让在item平分屏幕宽度$
|
||||||
|
*/
|
||||||
|
public class EqualSpaceItemDecoration extends RecyclerView.ItemDecoration {
|
||||||
|
private int spanCount;
|
||||||
|
private int spacing;
|
||||||
|
|
||||||
|
public EqualSpaceItemDecoration(int spanCount, int spacing) {
|
||||||
|
this.spanCount = spanCount;
|
||||||
|
this.spacing = spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
|
||||||
|
int position = parent.getChildAdapterPosition(view);
|
||||||
|
|
||||||
|
// 设置间距
|
||||||
|
outRect.left = spacing / 2;
|
||||||
|
outRect.right = spacing / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
|
||||||
|
super.onDraw(c, parent, state);
|
||||||
|
|
||||||
|
// 确保每个item宽度为屏幕的1/3
|
||||||
|
int childCount = parent.getChildCount();
|
||||||
|
int screenWidth = parent.getWidth();
|
||||||
|
int itemWidth = screenWidth / spanCount;
|
||||||
|
|
||||||
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
View child = parent.getChildAt(i);
|
||||||
|
ViewGroup.LayoutParams params = child.getLayoutParams();
|
||||||
|
params.width = itemWidth;
|
||||||
|
child.setLayoutParams(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -279,6 +279,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginBottom="@dimen/dp_15"
|
android:layout_marginBottom="@dimen/dp_15"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/cl_gift"
|
app:layout_constraintTop_toBottomOf="@+id/cl_gift"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/exchange_layout"/>
|
app:layout_constraintBottom_toTopOf="@+id/exchange_layout"/>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user