2025-09-26 16:27:38 +08:00
|
|
|
|
package com.xscm.moduleutil.view;
|
|
|
|
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import android.content.res.TypedArray;
|
|
|
|
|
|
import android.graphics.drawable.Drawable;
|
|
|
|
|
|
import android.util.AttributeSet;
|
|
|
|
|
|
import android.util.TypedValue;
|
|
|
|
|
|
import android.view.Gravity;
|
|
|
|
|
|
import android.view.View;
|
|
|
|
|
|
import android.view.animation.Animation;
|
|
|
|
|
|
import android.view.animation.RotateAnimation;
|
|
|
|
|
|
import android.widget.Button;
|
|
|
|
|
|
import android.widget.ImageView;
|
|
|
|
|
|
import android.widget.RelativeLayout;
|
|
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
|
|
|
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
|
|
|
|
|
|
|
|
import com.xscm.moduleutil.R;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class QXMeetGiftView extends RelativeLayout {
|
|
|
|
|
|
|
|
|
|
|
|
private TextView giftNameLabel;
|
|
|
|
|
|
private ImageView giftPriceBgView;
|
|
|
|
|
|
private Button giftCoin;
|
|
|
|
|
|
private ImageView bgImageView;
|
|
|
|
|
|
private ImageView giftBgImageView;
|
|
|
|
|
|
private ImageView giftImageView;
|
|
|
|
|
|
|
|
|
|
|
|
// 自定义属性变量
|
|
|
|
|
|
private int normalBgRes;
|
|
|
|
|
|
private int lockBgRes;
|
|
|
|
|
|
private int giftLightBgRes;
|
|
|
|
|
|
private int priceBgRes;
|
|
|
|
|
|
private int coinIconRes;
|
|
|
|
|
|
private int giftNameColor;
|
|
|
|
|
|
private int coinTextColor;
|
|
|
|
|
|
private float giftNameSize;
|
|
|
|
|
|
private float coinTextSize;
|
|
|
|
|
|
private int bgBottomMargin;
|
|
|
|
|
|
private int giftImageMargin;
|
|
|
|
|
|
private int priceBgHeight;
|
|
|
|
|
|
private int priceBgBottomMargin;
|
|
|
|
|
|
private int lockGiftSize;
|
|
|
|
|
|
private int rotateDuration;
|
|
|
|
|
|
|
|
|
|
|
|
private boolean isLockGift;
|
|
|
|
|
|
private Object model;
|
|
|
|
|
|
|
|
|
|
|
|
public QXMeetGiftView(Context context) {
|
|
|
|
|
|
this(context, null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public QXMeetGiftView(Context context, @Nullable AttributeSet attrs) {
|
|
|
|
|
|
this(context, attrs, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public QXMeetGiftView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
|
|
|
|
|
super(context, attrs, defStyleAttr);
|
|
|
|
|
|
// 解析自定义属性
|
|
|
|
|
|
initAttrs(context, attrs);
|
|
|
|
|
|
// 初始化子视图
|
|
|
|
|
|
initSubviews(context);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 解析自定义属性,设置默认值
|
|
|
|
|
|
*/
|
|
|
|
|
|
private void initAttrs(Context context, AttributeSet attrs) {
|
|
|
|
|
|
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.QXMeetGiftView);
|
|
|
|
|
|
|
|
|
|
|
|
// 背景资源(默认使用原代码中的资源)
|
|
|
|
|
|
normalBgRes = ta.getResourceId(R.styleable.QXMeetGiftView_normalBg, R.mipmap.xlh_g_2);
|
|
|
|
|
|
lockBgRes = ta.getResourceId(R.styleable.QXMeetGiftView_lockBg, R.mipmap.ic_launcher);
|
|
|
|
|
|
giftLightBgRes = ta.getResourceId(R.styleable.QXMeetGiftView_giftLightBg, R.mipmap.jinb);
|
|
|
|
|
|
priceBgRes = ta.getResourceId(R.styleable.QXMeetGiftView_priceBg, R.mipmap.ic_launcher);
|
|
|
|
|
|
coinIconRes = ta.getResourceId(R.styleable.QXMeetGiftView_coinIcon, R.mipmap.ic_launcher);
|
|
|
|
|
|
|
|
|
|
|
|
// 文字样式
|
|
|
|
|
|
giftNameColor = ta.getColor(R.styleable.QXMeetGiftView_giftNameColor, 0xFFFFFFFF);
|
|
|
|
|
|
coinTextColor = ta.getColor(R.styleable.QXMeetGiftView_coinTextColor, 0xFFC7BF62);
|
|
|
|
|
|
giftNameSize = ta.getDimension(R.styleable.QXMeetGiftView_giftNameSize, sp2px(12));
|
|
|
|
|
|
coinTextSize = ta.getDimension(R.styleable.QXMeetGiftView_coinTextSize, sp2px(10));
|
|
|
|
|
|
|
|
|
|
|
|
// 尺寸配置
|
|
|
|
|
|
bgBottomMargin = ta.getDimensionPixelOffset(R.styleable.QXMeetGiftView_bgBottomMargin, dp2px(19));
|
|
|
|
|
|
giftImageMargin = ta.getDimensionPixelOffset(R.styleable.QXMeetGiftView_giftImageMargin, dp2px(6));
|
|
|
|
|
|
priceBgHeight = ta.getDimensionPixelOffset(R.styleable.QXMeetGiftView_priceBgHeight, dp2px(15));
|
|
|
|
|
|
priceBgBottomMargin = ta.getDimensionPixelOffset(R.styleable.QXMeetGiftView_priceBgBottomMargin, dp2px(15));
|
|
|
|
|
|
lockGiftSize = ta.getDimensionPixelOffset(R.styleable.QXMeetGiftView_lockGiftSize, dp2px(62));
|
|
|
|
|
|
|
|
|
|
|
|
// 动画时长
|
|
|
|
|
|
rotateDuration = ta.getInt(R.styleable.QXMeetGiftView_rotateDuration, 3000);
|
|
|
|
|
|
|
|
|
|
|
|
ta.recycle(); // 回收资源,避免内存泄漏
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void initSubviews(Context context) {
|
|
|
|
|
|
// 1. 主背景
|
|
|
|
|
|
bgImageView = new ImageView(context);
|
|
|
|
|
|
bgImageView.setScaleType(ImageView.ScaleType.FIT_XY);
|
|
|
|
|
|
bgImageView.setImageResource(normalBgRes); // 使用自定义属性
|
|
|
|
|
|
LayoutParams bgParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
|
|
|
|
|
bgParams.addRule(ALIGN_PARENT_TOP);
|
|
|
|
|
|
bgParams.addRule(ALIGN_PARENT_LEFT);
|
|
|
|
|
|
bgParams.addRule(ALIGN_PARENT_RIGHT);
|
|
|
|
|
|
bgParams.bottomMargin = bgBottomMargin; // 使用自定义属性
|
|
|
|
|
|
addView(bgImageView, bgParams);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 礼物光效背景
|
|
|
|
|
|
giftBgImageView = new ImageView(context);
|
|
|
|
|
|
giftBgImageView.setScaleType(ImageView.ScaleType.FIT_XY);
|
|
|
|
|
|
giftBgImageView.setImageResource(giftLightBgRes); // 使用自定义属性
|
|
|
|
|
|
giftBgImageView.setVisibility(View.GONE);
|
|
|
|
|
|
LayoutParams giftBgParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
|
|
|
|
|
giftBgParams.addRule(ALIGN_PARENT_TOP);
|
|
|
|
|
|
giftBgParams.addRule(ALIGN_PARENT_LEFT);
|
|
|
|
|
|
giftBgParams.addRule(ALIGN_PARENT_RIGHT);
|
|
|
|
|
|
giftBgParams.bottomMargin = bgBottomMargin; // 使用自定义属性
|
|
|
|
|
|
addView(giftBgImageView, giftBgParams);
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 礼物图片
|
|
|
|
|
|
giftImageView = new ImageView(context);
|
|
|
|
|
|
giftImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
|
|
|
|
|
LayoutParams giftImageParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
|
|
|
|
|
|
giftImageParams.addRule(CENTER_IN_PARENT);
|
|
|
|
|
|
giftImageParams.setMargins(giftImageMargin, giftImageMargin, giftImageMargin, 0); // 使用自定义属性
|
|
|
|
|
|
addView(giftImageView, giftImageParams);
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 价格背景
|
|
|
|
|
|
giftPriceBgView = new ImageView(context);
|
|
|
|
|
|
giftPriceBgView.setImageResource(priceBgRes); // 使用自定义属性
|
|
|
|
|
|
LayoutParams priceBgParams = new LayoutParams(LayoutParams.MATCH_PARENT, priceBgHeight); // 使用自定义属性
|
|
|
|
|
|
priceBgParams.addRule(ALIGN_PARENT_BOTTOM);
|
|
|
|
|
|
priceBgParams.bottomMargin = priceBgBottomMargin; // 使用自定义属性
|
|
|
|
|
|
addView(giftPriceBgView, priceBgParams);
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 金币按钮
|
|
|
|
|
|
giftCoin = new Button(context);
|
|
|
|
|
|
giftCoin.setTextColor(coinTextColor); // 使用自定义属性
|
|
|
|
|
|
giftCoin.setTextSize(TypedValue.COMPLEX_UNIT_PX, coinTextSize); // 使用自定义属性
|
|
|
|
|
|
// 金币图标
|
|
|
|
|
|
Drawable coinDrawable = getResources().getDrawable(coinIconRes); // 使用自定义属性
|
|
|
|
|
|
coinDrawable.setBounds(0, 0, dp2px(12), dp2px(12));
|
|
|
|
|
|
giftCoin.setCompoundDrawables(coinDrawable, null, null, null);
|
|
|
|
|
|
giftCoin.setBackgroundColor(0x00000000); // 透明背景
|
|
|
|
|
|
LayoutParams coinParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
|
|
|
|
|
coinParams.addRule(CENTER_IN_PARENT, TRUE);
|
|
|
|
|
|
addView(giftCoin, coinParams);
|
|
|
|
|
|
|
|
|
|
|
|
// 6. 礼物名称
|
|
|
|
|
|
giftNameLabel = new TextView(context);
|
|
|
|
|
|
giftNameLabel.setTextColor(giftNameColor); // 使用自定义属性
|
|
|
|
|
|
giftNameLabel.setTextSize(TypedValue.COMPLEX_UNIT_PX, giftNameSize); // 使用自定义属性
|
|
|
|
|
|
giftNameLabel.setGravity(Gravity.CENTER);
|
|
|
|
|
|
LayoutParams nameParams = new LayoutParams(LayoutParams.MATCH_PARENT, priceBgHeight); // 使用自定义属性
|
|
|
|
|
|
nameParams.addRule(ALIGN_PARENT_BOTTOM);
|
|
|
|
|
|
addView(giftNameLabel, nameParams);
|
|
|
|
|
|
|
|
|
|
|
|
// 调整层级
|
|
|
|
|
|
bringChildToFront(giftPriceBgView);
|
|
|
|
|
|
bringChildToFront(giftCoin);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setIsLockGift(boolean isLockGift) {
|
|
|
|
|
|
this.isLockGift = isLockGift;
|
|
|
|
|
|
|
|
|
|
|
|
// 设置背景图片(使用自定义属性)
|
|
|
|
|
|
int bgResource = isLockGift ? lockBgRes : normalBgRes;
|
|
|
|
|
|
bgImageView.setImageResource(bgResource);
|
|
|
|
|
|
|
|
|
|
|
|
// 显示/隐藏光效背景
|
|
|
|
|
|
giftBgImageView.setVisibility(isLockGift ? View.VISIBLE : View.GONE);
|
|
|
|
|
|
|
|
|
|
|
|
// 调整礼物图片尺寸(使用自定义属性)
|
|
|
|
|
|
LayoutParams params = (LayoutParams) giftImageView.getLayoutParams();
|
|
|
|
|
|
if (isLockGift) {
|
|
|
|
|
|
params.width = lockGiftSize;
|
|
|
|
|
|
params.height = lockGiftSize;
|
|
|
|
|
|
params.setMargins(0, 0, 0, 0);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
params.width = LayoutParams.MATCH_PARENT;
|
|
|
|
|
|
params.height = LayoutParams.WRAP_CONTENT;
|
|
|
|
|
|
params.setMargins(giftImageMargin, giftImageMargin, giftImageMargin, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
giftImageView.setLayoutParams(params);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setModel(Object model) {
|
|
|
|
|
|
this.model = model;
|
|
|
|
|
|
// 实际业务中解析模型数据
|
|
|
|
|
|
/*
|
|
|
|
|
|
if (model instanceof QXDrawGiftModel) {
|
|
|
|
|
|
QXDrawGiftModel giftModel = (QXDrawGiftModel) model;
|
|
|
|
|
|
giftNameLabel.setText(giftModel.getGiftName());
|
|
|
|
|
|
giftCoin.setText(giftModel.getGiftPrice());
|
|
|
|
|
|
// Glide.with(getContext()).load(giftModel.getBaseImage()).into(giftImageView);
|
|
|
|
|
|
}
|
|
|
|
|
|
*/
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void startAnimation() {
|
|
|
|
|
|
// 礼物图片顺时针旋转(使用自定义动画时长)
|
|
|
|
|
|
RotateAnimation rotateAnimation = new RotateAnimation(
|
|
|
|
|
|
0, 360,
|
|
|
|
|
|
Animation.RELATIVE_TO_SELF, 0.5f,
|
|
|
|
|
|
Animation.RELATIVE_TO_SELF, 0.5f
|
|
|
|
|
|
);
|
|
|
|
|
|
rotateAnimation.setDuration(rotateDuration);
|
|
|
|
|
|
rotateAnimation.setRepeatCount(Animation.INFINITE);
|
|
|
|
|
|
rotateAnimation.setRepeatMode(Animation.RESTART);
|
|
|
|
|
|
rotateAnimation.setInterpolator(getContext(), android.R.anim.linear_interpolator);
|
|
|
|
|
|
giftImageView.startAnimation(rotateAnimation);
|
|
|
|
|
|
|
|
|
|
|
|
// 光效背景逆时针旋转
|
|
|
|
|
|
RotateAnimation rotateAnimation1 = new RotateAnimation(
|
|
|
|
|
|
0, -360,
|
|
|
|
|
|
Animation.RELATIVE_TO_SELF, 0.5f,
|
|
|
|
|
|
Animation.RELATIVE_TO_SELF, 0.5f
|
|
|
|
|
|
);
|
|
|
|
|
|
rotateAnimation1.setDuration(rotateDuration);
|
|
|
|
|
|
rotateAnimation1.setRepeatCount(Animation.INFINITE);
|
|
|
|
|
|
rotateAnimation1.setRepeatMode(Animation.RESTART);
|
|
|
|
|
|
rotateAnimation1.setInterpolator(getContext(), android.R.anim.linear_interpolator);
|
|
|
|
|
|
giftBgImageView.startAnimation(rotateAnimation1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void resetAnimation() {
|
|
|
|
|
|
giftImageView.clearAnimation();
|
|
|
|
|
|
giftBgImageView.clearAnimation();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void stopAnimation() {
|
|
|
|
|
|
giftImageView.clearAnimation();
|
|
|
|
|
|
giftBgImageView.clearAnimation();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// dp转px
|
|
|
|
|
|
private int dp2px(int dp) {
|
|
|
|
|
|
return (int) TypedValue.applyDimension(
|
|
|
|
|
|
TypedValue.COMPLEX_UNIT_DIP,
|
|
|
|
|
|
dp,
|
|
|
|
|
|
getResources().getDisplayMetrics()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// sp转px
|
|
|
|
|
|
private int sp2px(int sp) {
|
|
|
|
|
|
return (int) TypedValue.applyDimension(
|
|
|
|
|
|
TypedValue.COMPLEX_UNIT_SP,
|
|
|
|
|
|
sp,
|
|
|
|
|
|
getResources().getDisplayMetrics()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Getter方法
|
|
|
|
|
|
public TextView getGiftNameLabel() { return giftNameLabel; }
|
|
|
|
|
|
public ImageView getGiftPriceBgView() { return giftPriceBgView; }
|
|
|
|
|
|
public Button getGiftCoin() { return giftCoin; }
|
|
|
|
|
|
public ImageView getBgImageView() { return bgImageView; }
|
|
|
|
|
|
public ImageView getGiftBgImageView() { return giftBgImageView; }
|
|
|
|
|
|
public ImageView getGiftImageView() { return giftImageView; }
|
|
|
|
|
|
public boolean isLockGift() { return isLockGift; }
|
|
|
|
|
|
public Object getModel() { return model; }
|
|
|
|
|
|
}
|