修改交友布局

This commit is contained in:
2025-08-26 19:34:44 +08:00
commit 8eb8ac5397
3152 changed files with 1442170 additions and 0 deletions

View File

@@ -0,0 +1,609 @@
package com.xscm.moduleutil.widget;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import com.xscm.moduleutil.R;
public class PKProgressBar extends View {
// 文字背景颜色
private int textBgColor = 0;
// 绘制跟随进度条移动的数字的画笔
private Paint paintNumber;
private Paint bitmapPaint;
private Paint paintBar;
private Paint paintOtherBar;
private Paint paintLight;
private Paint leftTextPaintBg;
private Paint rightTextPaintBg;
private int backGroundColor = Color.GRAY;
private int barColor = Color.RED;
private Drawable leftDrawable;
private Drawable rightDrawable;
private Drawable rightDrawableOne;
private Drawable rightDrawableTwo;
private Drawable rightDrawableThree;
private OnProgressChangeListener onProgressChangeListener;
private int halfDrawableWidth = 0;
private int halfDrawableHeight = 0;
private int barPadding = 0;
private boolean isRound = true;
private float progress = 50f;
private float max = 100f;
private double progressPercentage = 0.5;
private float viewWidth = 0f;
private int viewHeight = 0;
private int progressWidth = 100;
private RectF rectFBG = new RectF();
private RectF rectFPB = new RectF();
private RectF rectFPBO = new RectF();
private Path barRoundPath = new Path();
private Path barRoundPathOther = new Path();
private Rect rectLeftText = new Rect();
private Rect rectRightText = new Rect();
private Rect rectLeftFollowText = new Rect();
private Rect rectRightFollowText = new Rect();
private Paint paintRightText;
private Paint paintLeftText;
private Paint paintBackGround;
// 是否使用颜色渐变器
private boolean isGradient = false;
// 颜色渐变器
private LinearGradient linearGradient;
private LinearGradient linearGradientOther;
private int gradientStartColor = Color.RED;
private int gradientEndColor = Color.YELLOW;
private int otherGradientStartColor = Color.RED;
private int otherGradientEndColor = Color.YELLOW;
private int barStartWidth = 0;
// 进度条最大绘制位置与最小绘制位置
private int barEndWidth = 0;
// 圆角大小
private float barRadioSize = 0f;
private int textColor = Color.WHITE;
private int textSize = 12;
private boolean textIsBold = true;
// 蓝方
private String leftTextStr = "";
// 红方
private String rightTextStr = "";
private String leftTeamName = "";
private String leftTeamCount = "";
private String rightTeamName = "";
private String rightTeamCount = "";
private String leftFollowTextStr = "";
private String rightFollowTextStr = "";
private Bitmap lightBitmap;
private int lightDrawableId = 0;
private float leftTextStrWidth = 0f;
private float leftTextStrHeight = 0f;
private float leftTextStrMargin = 21;
private float commonMargin = 6;
private float leftTextStrBg = 57;
private float rightTextStrWidth = 0f;
private float rightTextStrHeight = 0f;
private float rightTextStrMargin = 21;
private float leftFollowWidth = 0f;
private float leftFollowHeight = 0f;
private float rightFollowWidth = 0f;
private float rightFollowHeight = 0f;
private float followMargin = 16;
/**
* 左侧队名显示状态
*/
private boolean leftTeamNameVisible = true;
/**
* 左侧团队人数的显示状态
*/
private boolean leftTeamCountVisible = true;
/**
* 右侧队名显示状态
*/
private boolean rightTeamNameVisible = true;
/**
* 右侧团队人数的显示状态
*/
private boolean rightTeamCountVisible = true;
/**
* 左侧的队名宽度
*/
private float leftTeamNameWidth = 0f;
/**
* 左侧的团队人数宽度
*/
private float leftTeamCountWidth = 0f;
/**
* 右侧的队名的宽度
*/
private float rightTeamNameWidth = 0f;
/**
* 右侧的团队人数宽度
*/
private float rightTeamCountWidth = 0f;
/**
* 右侧用户头像边距
*/
private final float rightAvatarMargin = 10;
/**
* 右侧用户头像宽度
*/
private final float rightAvatarwidth = 58;
public PKProgressBar(Context context) {
super(context);
init();
}
public PKProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PKProgressBar_pk, 0, 0);
backGroundColor = typedArray.getColor(R.styleable.PKProgressBar_pk_backGroundColor, Color.GRAY);
barColor = typedArray.getColor(R.styleable.PKProgressBar_pk_barColor, Color.RED);
leftDrawable = typedArray.getDrawable(R.styleable.PKProgressBar_pk_leftDrawableBg);
rightDrawable = typedArray.getDrawable(R.styleable.PKProgressBar_pk_rightDrawableBg);
halfDrawableWidth = typedArray.getDimensionPixelSize(R.styleable.PKProgressBar_pk_halfDrawableWidth, 1);
halfDrawableHeight = typedArray.getDimensionPixelSize(R.styleable.PKProgressBar_pk_halfDrawableHeight, 1);
barPadding = typedArray.getDimensionPixelSize(R.styleable.PKProgressBar_pk_barPadding, 0);
isRound = typedArray.getBoolean(R.styleable.PKProgressBar_pk_isRound, true);
max = typedArray.getInt(R.styleable.PKProgressBar_pk_max, 100);
lightDrawableId = typedArray.getResourceId(R.styleable.PKProgressBar_pk_lightDrawable, 0);
textColor = typedArray.getColor(R.styleable.PKProgressBar_pk_textColor, Color.BLACK);
textSize = typedArray.getDimensionPixelSize(R.styleable.PKProgressBar_pk_textSize, 13);
textIsBold = typedArray.getBoolean(R.styleable.PKProgressBar_pk_textIsBold, false);
isGradient = typedArray.getBoolean(R.styleable.PKProgressBar_pk_isGradient, false);
gradientStartColor = typedArray.getColor(R.styleable.PKProgressBar_pk_gradientStartColor, Color.RED);
gradientEndColor = typedArray.getColor(R.styleable.PKProgressBar_pk_gradientEndColor, Color.YELLOW);
otherGradientStartColor = typedArray.getColor(R.styleable.PKProgressBar_pk_otherGradientStartColor, Color.RED);
otherGradientEndColor = typedArray.getColor(R.styleable.PKProgressBar_pk_otherGradientEndColor, Color.YELLOW);
typedArray.recycle();
init();
}
public PKProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// 底部边框背景
paintBackGround = new Paint();
paintBackGround.setColor(backGroundColor);
paintBackGround.setAntiAlias(true);
paintLight = new Paint();
paintLight.setAntiAlias(true);
// 左半部分进度条
paintBar = new Paint();
paintBar.setColor(barColor);
paintBar.setAntiAlias(true);
// 右半部分进度条
paintOtherBar = new Paint();
paintOtherBar.setColor(barColor);
paintOtherBar.setAntiAlias(true);
// 左半部分文字
// Typeface plain = Typeface.createFromAsset(getContext().getAssets(), "Roboto-BlackItalic.ttf");/**/
paintLeftText = new Paint();
// paintLeftText.setTypeface(plain);
paintLeftText.setStyle(Paint.Style.FILL);
paintLeftText.setColor(textColor);
paintLeftText.setTextSize(textSize);
leftTextStrWidth = paintLeftText != null ? paintLeftText.measureText(leftTextStr) : 0;
leftTextStrHeight = paintLeftText != null ? paintLeftText.descent() - paintLeftText.ascent() : 0;
// 团队数字
// Typeface plainNumber = Typeface.createFromAsset(getContext().getAssets(), "Roboto-BlackItalic.ttf");
paintNumber = new Paint();
// paintNumber.setTypeface(plainNumber);
paintNumber.setStyle(Paint.Style.FILL);
paintNumber.setColor(textColor);
paintNumber.setTextSize(24);
// 左半部文字的背景
leftTextPaintBg = new Paint();
leftTextPaintBg.setStyle(Paint.Style.FILL);
leftTextPaintBg.setColor(textBgColor);
leftTextPaintBg.setAntiAlias(true);
// 右半部分文字
paintRightText = new Paint();
paintRightText.setStyle(Paint.Style.FILL);
paintRightText.setColor(textColor);
paintRightText.setTextSize(textSize);
paintRightText.setFakeBoldText(textIsBold);
paintRightText.setAntiAlias(true);
paintRightText.setTextSkewX(-0.25f);
if (lightDrawableId != 0) {
lightBitmap = BitmapFactory.decodeResource(getResources(), lightDrawableId);
}
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
getViewTreeObserver().removeOnPreDrawListener(this);
// 是否需要渐变器
if (isGradient) {
linearGradient = new LinearGradient(
0f,
viewHeight / 2f,
progressWidth,
viewHeight / 2f,
gradientStartColor,
gradientEndColor,
Shader.TileMode.CLAMP
);
linearGradientOther = new LinearGradient(
0f,
viewHeight / 2f,
progressWidth,
viewHeight / 2f,
otherGradientStartColor,
otherGradientEndColor,
Shader.TileMode.CLAMP
);
if (paintBar != null) {
paintBar.setShader(linearGradient);
}
if (paintOtherBar != null) {
paintOtherBar.setShader(linearGradientOther);
}
}
return false;
}
});
}
@Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 光标水平位置
viewWidth = ((progressWidth - 3 * barPadding) * (float) progressPercentage + barPadding);
viewWidth = Math.max(viewWidth, leftTextStrBg + leftTextStrMargin + leftFollowWidth);
viewWidth = Math.min(
viewWidth,
progressWidth - commonMargin - barPadding - rightAvatarMargin - rightAvatarwidth - rightFollowWidth - followMargin
);
viewHeight = getHeight();
// 圆角大小,为实际进度条高度一半
if (isRound) {
barRadioSize = (viewHeight - barPadding * 2) / 2f;
}
// 绘制底部边框
drawBackground(canvas);
// 绘制左半部分进度条
drawLeftBar(canvas);
// 绘制右半部分进度条
drawRightBar(canvas);
// 绘制透明图层
drawPicture(canvas);
// 绘制横向半透明光柱
drawLight(canvas);
// 绘制跟随进度条移动的文字
drawFollowText(canvas);
// 绘制队伍信息
drawTeamInfoText(canvas);
}
private void drawFollowText(Canvas canvas) {
float leftFollowStart = getBoundaryPosition() - leftFollowWidth - halfDrawableWidth - followMargin;
float rightFollowStart = getBoundaryPosition() + rightFollowWidth + halfDrawableWidth + followMargin;
leftTeamCountVisible = leftFollowStart > leftTextStrBg + leftTeamNameWidth + leftTextStrMargin * 2 + leftTeamCountWidth;
leftTeamNameVisible = leftFollowStart > leftTextStrBg + commonMargin + leftTeamNameWidth;
rightTeamCountVisible = rightFollowStart < (progressWidth - commonMargin * 2 - barPadding - rightAvatarMargin - rightAvatarwidth - rightTeamNameWidth - rightTeamCountWidth);
rightTeamNameVisible = rightFollowStart < (progressWidth - commonMargin - rightTeamNameWidth - barPadding - rightAvatarMargin - rightAvatarwidth);
}
private void drawLight(Canvas canvas) {
if (lightBitmap == null) {
return;
}
canvas.save();
// 将画布坐标系移动到画布中央
canvas.translate(0f, barPadding);
Rect src = new Rect(barStartWidth, 0, barEndWidth, (viewHeight - barPadding) / 2);
canvas.drawBitmap(lightBitmap, src, src, paintLight);
canvas.restore();
}
private void drawBackground(Canvas canvas) {
canvas.save();
rectFBG.set(0f, 0f, progressWidth, viewHeight);
if (isRound) {
Path path = new Path();
path.addRoundRect(new RectF(0f, 0f, getMeasuredWidth(), getMeasuredHeight()), viewHeight / 2f, viewHeight / 2f, Path.Direction.CW);
// 先对canvas进行裁剪
canvas.clipPath(path, Region.Op.INTERSECT);
} else {
if (paintBackGround != null) {
canvas.drawRect(rectFBG, paintBackGround);
}
}
canvas.restore();
}
private void drawLeftBar(Canvas canvas) {
float right = getBoundaryPosition();
float[] radios = {
barRadioSize, barRadioSize, 0f, 0f, 0f, 0f, barRadioSize, barRadioSize
};
canvas.save();
rectFPB.set(barPadding, barPadding, right - halfDrawableWidth, viewHeight - barPadding);
barRoundPath.reset();
barRoundPath.addRoundRect(rectFPB, radios, Path.Direction.CCW);
barRoundPath.close();
if (isRound) {
if (paintBar != null) {
canvas.drawPath(barRoundPath, paintBar);
}
} else {
if (paintBar != null) {
canvas.drawRect(rectFPB, paintBar);
}
}
canvas.restore();
}
private void drawRightBar(Canvas canvas) {
float left = getBoundaryPosition();
float[] radios = {
0f, 0f,
barRadioSize, barRadioSize,
barRadioSize, barRadioSize, 0f, 0f
};
canvas.save();
rectFPBO.set(left + halfDrawableWidth, barPadding, barEndWidth, viewHeight - barPadding);
barRoundPathOther.reset();
barRoundPathOther.addRoundRect(rectFPBO, radios, Path.Direction.CCW);
barRoundPathOther.close();
if (isRound) {
if (paintOtherBar != null) {
canvas.drawPath(barRoundPathOther, paintOtherBar);
}
} else {
if (paintOtherBar != null) {
canvas.drawRect(rectFPBO, paintOtherBar);
}
}
canvas.restore();
}
private void drawTeamInfoText(Canvas canvas) {
// 左侧
// 绘制文字的背景
if (leftTextPaintBg != null) {
leftTextPaintBg.setColor(textBgColor);
canvas.drawRoundRect(13, 13, 57, viewHeight - 13, viewHeight / 2f, viewHeight / 2f, leftTextPaintBg);
}
if (paintLeftText != null) {
canvas.drawText(leftTextStr, leftTextStrMargin, viewHeight / 2f + leftTextStrHeight / 3f, paintLeftText);
}
if (leftTeamNameVisible && paintLeftText != null) {
// 队名
canvas.drawText(leftTeamName, leftTextStrBg + commonMargin, viewHeight / 2f + leftTextStrHeight / 3f, paintLeftText);
}
if (leftTeamCountVisible && paintLeftText != null) {
// 队伍人数
// canvas.drawText(leftTeamCount, leftTextStrBg + leftTeamNameWidth + commonMargin * 2, viewHeight / 2f + leftTextStrHeight / 3f, paintLeftText);
}
// 右侧
if (rightTeamNameVisible && paintRightText != null) {
// 右侧队名
canvas.drawText(rightTeamName, progressWidth - commonMargin - rightTeamNameWidth - barPadding - rightAvatarMargin - rightAvatarwidth, viewHeight / 2f + leftTextStrHeight / 3f, paintRightText);
}
if (rightTeamCountVisible && paintRightText != null) {
// 右侧团队人数
// canvas.drawText(rightTeamCount, progressWidth - commonMargin * 2 - barPadding - rightAvatarMargin - rightAvatarwidth - rightTeamNameWidth - rightTeamCountWidth, viewHeight / 2f + leftTextStrHeight / 3f, paintRightText);
}
}
/**
* 获取极限位置进度条的绘制位置
* 1. 最左边
* 2. 最左边到圆角区段位置
* 3. 中间正常位置
* 4. 最右边圆角区段位置
* 5. 最右边
*
* @return 极限位置进度条的绘制位置
*/
private float getBoundaryPosition() {
// 默认为计算的比例位置
float boundaryPos = viewWidth;
if (progressPercentage == 0.0 || viewWidth == barStartWidth) {
// 光标位于最左边
boundaryPos = barPadding + leftTextStrBg + leftTextStrMargin + leftFollowWidth;
} else if (progressPercentage == 1.0 || viewWidth == barEndWidth) {
// 光标位于最右边
boundaryPos = barEndWidth - rightAvatarwidth - rightAvatarMargin;
} else if ((viewWidth - barStartWidth < barRadioSize || viewWidth - barStartWidth == barRadioSize)
&& viewWidth > barStartWidth) {
boundaryPos = Math.max(viewWidth, barRadioSize + barStartWidth);
} else if ((viewWidth > barEndWidth - barRadioSize || viewWidth == barEndWidth - barRadioSize)
&& viewWidth < barEndWidth) {
// 光标位于进度条右侧弧形区域
boundaryPos = Math.min(viewWidth, barEndWidth - barRadioSize);
}
return boundaryPos;
}
private void drawPicture(Canvas canvas) {
if (leftDrawable != null) {
leftDrawable.setBounds(0, 0, 180, viewHeight);
leftDrawable.draw(canvas);
}
if (rightDrawable != null) {
rightDrawable.setBounds(
(int) rectFPBO.right - 180,
(int) rectFPBO.top,
(int) rectFPBO.right,
(int) rectFPBO.bottom
);
rightDrawable.draw(canvas);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
if (getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
width = halfDrawableWidth * 2;
}
if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) {
height = halfDrawableHeight * 2;
}
// 记录进度条总长度
progressWidth = width;
// 记录进度条起始位置
barStartWidth = barPadding;
// 记录进度条结束位置
barEndWidth = progressWidth - barPadding;
setMeasuredDimension(width, height);
leftTextStrWidth = paintRightText != null ? paintRightText.measureText(leftTextStr) : 0;
leftTextStrHeight = paintLeftText != null ? paintLeftText.descent() - paintLeftText.ascent() : 0;
rightTextStrWidth = paintRightText != null ? paintRightText.measureText(rightTextStr) : 0;
rightTextStrHeight = paintRightText != null ? paintRightText.descent() - paintRightText.ascent() : 0;
leftFollowWidth = paintNumber != null ? paintNumber.measureText(leftFollowTextStr) : 0;
leftFollowHeight = paintNumber != null ? paintNumber.descent() - paintNumber.ascent() : 0;
rightFollowWidth = paintNumber != null ? paintNumber.measureText(rightFollowTextStr) : 0;
rightFollowHeight = paintNumber != null ? paintNumber.descent() - paintNumber.ascent() : 0;
rightTeamNameWidth = paintLeftText != null ? paintLeftText.measureText(rightTeamName) : 0;
rightTeamCountWidth = paintLeftText != null ? paintLeftText.measureText(rightTeamCount) : 0;
leftTeamNameWidth = paintLeftText != null ? paintLeftText.measureText(leftTeamName) : 0;
leftTeamCountWidth = paintLeftText != null ? paintLeftText.measureText(leftTeamCount) : 0;
}
/**
* 进度变化监听器接口
*/
public interface OnProgressChangeListener {
/**
* 当进度发生变化时触发
*
* @param progress 当前进度值
*/
void onOnProgressChange(int progress);
/**
* 当进度完成时触发
*/
void onOnProgressFinish();
}
/**
* 根据左右值设置动画进度
*
* @param leftValue 左值
* @param rightValue 右值
*/
public synchronized void setAnimProgress(long leftValue, long rightValue) {
leftFollowTextStr = String.valueOf(leftValue);
rightFollowTextStr = String.valueOf(rightValue);
if (leftValue + rightValue == 0L) {
setAnimProgress(50f);
} else {
setAnimProgress(100f * leftValue / (leftValue + rightValue));
}
}
/**
* 传入百分比值设置动画进度
*
* @param progressValue 百分比值
*/
public void setAnimProgress(float progressValue) {
if (progressValue < 0 || progressValue > 100) {
return;
}
ValueAnimator animator = ValueAnimator.ofFloat(progress, progressValue);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
setProgress(Float.parseFloat(valueAnimator.getAnimatedValue().toString()));
}
});
Interpolator interpolator = new AccelerateDecelerateInterpolator();
animator.setInterpolator(interpolator);
animator.setDuration((long) (Math.abs(progress - progressValue) * 20));
animator.start();
}
public void setProgress(float progressValue) {
if (progress <= max) {
progress = progressValue;
} else if (progress < 0) {
progress = 0f;
} else {
progress = max;
}
progressPercentage = progress / max;
doProgressRefresh();
invalidate();
}
private synchronized void doProgressRefresh() {
if (onProgressChangeListener != null) {
onProgressChangeListener.onOnProgressChange((int) progress);
if (progress >= max) {
onProgressChangeListener.onOnProgressFinish();
}
}
}
// 设置颜色渐变器
public void setLinearGradient(LinearGradient linearGradient) {
this.linearGradient = linearGradient;
}
// 设置进度监听器
public void setOnProgressChangeListener(OnProgressChangeListener onProgressChangeListener) {
this.onProgressChangeListener = onProgressChangeListener;
}
}