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

425 lines
17 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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();
}
}