JKBaseLib/BaseLibrary/src/main/java/com/tfq/library/view/SlideDownView.java

425 lines
17 KiB
Java
Raw Normal View History

2025-06-30 13:49:41 +08:00
package com.tfq.library.view;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.tfq.library.R;
import com.tfq.library.utils.LogK;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
/**
* Description:
* Created by JiangKe .
*/
public class SlideDownView extends LinearLayout {
// 动画相关属性
private final boolean isExpanded = false;
private float mTextTitleSize = 15f;
private float mTextContentSize = 12f;
private float targetTranslationY; // 目标位置的Y轴偏移量
private float overshootTranslationY; // 超过目标位置的Y轴偏移量
private String mTextTitle = "";
private String mTextContent = "";
private int mMILLISECONDS;
private boolean mViewCenter;
private int mImageView;
private int view_type;//0:通过(默认);1:error
private int view_bg = Color.parseColor("#4CB050");
private DelayedTaskManager taskManager;
public SlideDownView(Context context) {
super(context);
initView(null);
}
public SlideDownView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView(attrs);
}
public SlideDownView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(attrs);
}
private void initView(AttributeSet attrs) {
if (null != attrs) {
//获取到自定义xml的数据
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.SlideDownView);
mImageView = typedArray.getResourceId(R.styleable.SlideDownView_custom_image, 0);
mTextTitle = typedArray.getString(R.styleable.SlideDownView_text_title);
mTextTitleSize = typedArray.getFloat(R.styleable.SlideDownView_text_title_size, mTextTitleSize);
mTextContent = typedArray.getString(R.styleable.SlideDownView_text_content);
mTextContentSize = typedArray.getFloat(R.styleable.SlideDownView_text_content_size, mTextContentSize);
// mTextMarquee = typedArray.getBoolean(R.styleable.SlideDownView_boldMarquee, false);
mMILLISECONDS = typedArray.getInteger(R.styleable.SlideDownView_hide_milliseconds, 300);
mViewCenter = typedArray.getBoolean(R.styleable.SlideDownView_view_center, true);
typedArray.recycle();
}
addLinearLayoutView();
initThreadPool();
setLayerType(LAYER_TYPE_SOFTWARE, null);
setWillNotDraw(false);
}
private void initThreadPool() {
taskManager = new DelayedTaskManager();
}
// 在Activity的onCreate或其他适当位置调用此方法
private void addLinearLayoutView() {
// 获取应用上下文
Context context = getContext();
// 创建外层水平LinearLayout
LinearLayout mainLayout = new LinearLayout(context);
// 设置LayoutParams并添加marginTop
LinearLayout.LayoutParams mainParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
// 转换30dp为像素值
mainLayout.setLayoutParams(mainParams);
mainLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
hideFunctionBar();
}
});
// 保留原有其他属性设置
mainLayout.setOrientation(LinearLayout.HORIZONTAL);
// mainLayout.setGravity(Gravity.CENTER_VERTICAL);
if (mViewCenter) {
mainLayout.setGravity(Gravity.CENTER);
} else {
mainLayout.setGravity(Gravity.CENTER_VERTICAL);
}
int paddingHorizontal = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());
int paddingLeft = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, getResources().getDisplayMetrics());
int paddingTop = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 35, getResources().getDisplayMetrics());
mainLayout.setPadding(paddingLeft, paddingTop, paddingHorizontal, 0);
mainLayout.setBackgroundColor(view_bg);
mainLayout.setId(R.id.main_layout);
// 创建ImageView
ImageView imageView = new ImageView(context);
LinearLayout.LayoutParams imageParams = new LinearLayout.LayoutParams((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 70, getResources().getDisplayMetrics()), (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 70, getResources().getDisplayMetrics()));
imageView.setLayoutParams(imageParams);
imageView.setPadding((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics()), (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics()), (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics()), (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics()));
imageView.setImageResource(R.drawable.ic_place);
imageView.setId(R.id.image_view); // 确保在ids.xml中定义了此ID
if (mImageView != 0) {
imageView.setVisibility(VISIBLE);
} else {
imageView.setVisibility(GONE);
}
// 创建内层垂直LinearLayout
LinearLayout innerLayout = new LinearLayout(context);
LinearLayout.LayoutParams innerParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
int marginLeft = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics());
innerParams.setMargins(0, 0, 0, 0);
innerLayout.setLayoutParams(innerParams);
innerLayout.setOrientation(LinearLayout.VERTICAL);
// 创建标题TextView
TextView tvTitle = new TextView(context);
tvTitle.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
// 新增省略号和单行设置
tvTitle.setEllipsize(TextUtils.TruncateAt.END); // 末尾显示省略号
tvTitle.setMaxLines(1); // 限制为单行
tvTitle.setSingleLine(true); // 旧版兼容方案(可选)
tvTitle.setHorizontallyScrolling(true); // 防止自动换行
tvTitle.setText(mTextTitle);
tvTitle.setTextColor(ContextCompat.getColor(context, R.color.white));
tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, mTextTitleSize);
tvTitle.setTypeface(null, Typeface.BOLD);
tvTitle.setId(R.id.tv_title);
if (!TextUtils.isEmpty(mTextTitle)) {
tvTitle.setVisibility(VISIBLE);
} else {
tvTitle.setVisibility(GONE);
}
// 创建分隔线View
View divider = new View(context);
LinearLayout.LayoutParams dividerParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics()));
divider.setLayoutParams(dividerParams);
divider.setBackgroundColor(Color.TRANSPARENT); // 根据实际颜色设置
divider.setId(R.id.view_space);
// 创建内容TextView
TextView tvContent = new TextView(context);
tvContent.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
// 新增省略号和单行设置
tvContent.setEllipsize(TextUtils.TruncateAt.END); // 末尾显示省略号
tvContent.setMaxLines(1); // 限制为单行
tvContent.setSingleLine(true); // 旧版兼容方案(可选)
tvContent.setHorizontallyScrolling(true); // 防止自动换行
tvContent.setText(mTextContent);
tvContent.setTextColor(ContextCompat.getColor(context, R.color.white));
tvContent.setTextSize(TypedValue.COMPLEX_UNIT_DIP, mTextContentSize);
tvContent.setId(R.id.tv_content);
if (!TextUtils.isEmpty(mTextContent)) {
tvContent.setVisibility(VISIBLE);
} else {
tvContent.setVisibility(GONE);
}
if (!TextUtils.isEmpty(mTextTitle) && !TextUtils.isEmpty(mTextContent)) {
divider.setVisibility(VISIBLE);
} else {
divider.setVisibility(GONE);
}
innerLayout.setGravity(Gravity.CENTER);
// 组装内层布局
innerLayout.addView(tvTitle);
innerLayout.addView(divider);
innerLayout.addView(tvContent);
// 组装外层布局
mainLayout.addView(imageView);
mainLayout.addView(innerLayout);
// 设置为内容视图
addView(mainLayout);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 1. 测量所有子视图
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
// 2. 根据子视图计算父容器尺寸(此处以最大子宽度和累加高度为例)
int maxChildWidth = 0;
int totalHeight = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
maxChildWidth = Math.max(maxChildWidth, child.getMeasuredWidth());
totalHeight += child.getMeasuredHeight();
}
// 3. 设置父容器最终尺寸
setMeasuredDimension(resolveSize(maxChildWidth, widthMeasureSpec), resolveSize(totalHeight, heightMeasureSpec));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int currentTop = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
// 将子视图纵向排列(示例布局)
child.layout(0, currentTop, child.getMeasuredWidth(), currentTop + child.getMeasuredHeight());
currentTop += child.getMeasuredHeight();
}
}
public void hideFunctionBar() {
animate().translationY(-getHeight() * 1.5f) // 向上移动 1.5 倍高度
.setDuration(mMILLISECONDS).setInterpolator(new AccelerateInterpolator()).start();
}
/**
* n毫秒后执行隐藏
*
* @param MILLISECONDS 毫秒
*/
public void hideFunctionBar(long MILLISECONDS) {
animate().translationY(-getHeight() * 1.5f) // 向上移动 1.5 倍高度
.setDuration(MILLISECONDS).setInterpolator(new AccelerateInterpolator()).start();
}
public void showFunctionBar() {
hideFunctionBar(0);
// 将15dp转换为像素值
final float overshoot = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());
AnimatorSet set = new AnimatorSet();
set.playSequentially(ObjectAnimator
.ofFloat(this, "translationY", overshoot)
.setDuration(300), ObjectAnimator.ofFloat(this, "translationY", 0)
.setDuration(200)
);
set.setInterpolator(new AccelerateDecelerateInterpolator());
set.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// 动画开始时触发
LogK.e("Animation 动画开始");
taskManager.scheduleTask(3000, () -> {
// 延迟2秒后执行的实际操作如显示Toast
LogK.e("执行任务=" + System.currentTimeMillis());
hideFunctionBar();
});
}
@Override
public void onAnimationEnd(Animator animation) {
// 动画完成时触发回调整个AnimatorSet执行完毕
LogK.e("Animation 动画完成");
}
@Override
public void onAnimationCancel(Animator animation) {
// 动画被取消时触发
LogK.e("Animation 动画被取消");
}
@Override
public void onAnimationRepeat(Animator animation) {
// 动画重复时触发(仅适用于循环动画)
LogK.e("Animation 循环动画");
}
});
set.start();
}
public void setTextTitle(String mTextTitle) {
this.mTextTitle = mTextTitle;
invalidate();
}
public void setTextTitleSize(int mTextTitleSize) {
this.mTextTitleSize = mTextTitleSize;
invalidate();
}
public void setTextContent(String mTextContent) {
this.mTextContent = mTextContent;
invalidate();
}
public void setTextContentSize(int mTextContentSize) {
this.mTextContentSize = mTextContentSize;
invalidate();
}
public void setCustomImage(int mImageView) {
this.mImageView = mImageView;
invalidate();
}
public void setHide_milliseconds(int hide_milliseconds) {
this.mMILLISECONDS = hide_milliseconds;
}
public void setBackgroundColor(int view_bg) {
this.view_bg = view_bg;
invalidate();
}
public void setBackgroundColor(String view_bg) {
this.view_bg = Color.parseColor(view_bg);
invalidate();
}
public void setType(int view_type) {
this.view_type = view_type;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
TextView tv_title = findViewById(R.id.tv_title);
tv_title.setText(mTextTitle);
tv_title.setTextSize(mTextTitleSize);
TextView tv_content = findViewById(R.id.tv_content);
tv_content.setText(mTextContent);
tv_content.setTextSize(mTextContentSize);
ImageView image_view = findViewById(R.id.image_view);
View view_space = findViewById(R.id.view_space);
if (!TextUtils.isEmpty(mTextTitle) && !TextUtils.isEmpty(mTextContent)) {
view_space.setVisibility(VISIBLE);
tv_title.setVisibility(VISIBLE);
tv_content.setVisibility(VISIBLE);
} else {
view_space.setVisibility(GONE);
if (TextUtils.isEmpty(mTextTitle)) {
tv_title.setVisibility(GONE);
} else {
tv_title.setVisibility(VISIBLE);
}
if (TextUtils.isEmpty(mTextContent)) {
tv_content.setVisibility(GONE);
} else {
tv_content.setVisibility(GONE);
}
}
if (mImageView != 0) {
image_view.setVisibility(VISIBLE);
image_view.setImageResource(mImageView);
} else {
image_view.setVisibility(GONE);
}
view_bg = view_type==0? Color.parseColor("#4CB050") : Color.parseColor("#FF4443");
LinearLayout main_layout = findViewById(R.id.main_layout);
main_layout.setBackgroundColor(view_bg);
}
}
class DelayedTaskManager {
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
private final Handler mainHandler = new Handler(Looper.getMainLooper());
private ScheduledFuture<?> pendingTask;
// 提交延迟任务UI线程调用
public void scheduleTask(final long time, final Runnable task) {
// 取消之前的任务
if (pendingTask != null) {
pendingTask.cancel(true);
}
// 提交新任务延迟2秒执行
pendingTask = executor.schedule(() -> {
// 切换到主线程执行实际任务如更新UI
mainHandler.post(task);
}, time, TimeUnit.MILLISECONDS);
}
// 关闭线程池,避免内存泄漏
public void shutdown() {
executor.shutdownNow();
}
}