Skip to content

Instantly share code, notes, and snippets.

@puke3615
Created July 14, 2021 07:31
Show Gist options
  • Save puke3615/09db048bd27db7f11a5ed802177dd58d to your computer and use it in GitHub Desktop.
Save puke3615/09db048bd27db7f11a5ed802177dd58d to your computer and use it in GitHub Desktop.
ActivityFloatHelper
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.Nullable;
/**
* 底部悬浮视图辅助类
*
* @author puke
* @version 2019/6/10
*/
public class ActivityFloatHelper {
public final ViewGroup rootLayout;
public final View mask;
public final ViewGroup bodyContainer;
private final Activity activity;
private final View view;
private final int layout;
// 默认空出屏幕的 3/8
private int topOffset = getScreenHeight() * 3 / 8;
private int animationDuration = 300;
private ValueAnimator animator;
private boolean isShow;
@Nullable
private View inflatedLayer;
@SuppressLint("InflateParams")
public ActivityFloatHelper(Activity activity, @LayoutRes int layout) {
this.activity = activity;
this.layout = layout;
LayoutInflater inflater = LayoutInflater.from(activity);
view = inflater.inflate(R.layout.view_activity_float, null);
rootLayout = view.findViewById(R.id.view_root_layout);
mask = view.findViewById(R.id.view_mask);
bodyContainer = view.findViewById(R.id.view_body_container);
bodyContainer.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return true;
}
});
rootLayout.setOnClickListener(v -> hide());
}
public <V extends View> V findViewById(@IdRes int id) {
return view.findViewById(id);
}
public ActivityFloatHelper setAnimationDuration(int animationDuration) {
this.animationDuration = animationDuration;
if (animator != null) {
animator.cancel();
animator = null;
}
return this;
}
public ActivityFloatHelper setTopOffset(int topOffset) {
this.topOffset = topOffset;
if (animator != null) {
animator.cancel();
animator = null;
}
return this;
}
@Nullable
public View show() {
if (!isShow) {
inflatedLayer = addViewIfNeed();
isShow = true;
initAnimatorIfNeed();
animator.start();
}
return inflatedLayer;
}
public void hide() {
if (!isShow) {
return;
}
isShow = false;
addViewIfNeed();
initAnimatorIfNeed();
animator.reverse();
}
@Nullable
private View addViewIfNeed() {
if (view.getParent() == null) {
// 默认出于屏幕之下
ViewGroup.MarginLayoutParams layoutParams = new ViewGroup.MarginLayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
layoutParams.topMargin = getScreenHeight() - topOffset;
activity.addContentView(view, layoutParams);
setFloatLayoutMarginTop(topOffset);
inflatedLayer = View.inflate(activity, layout, bodyContainer);
}
return inflatedLayer;
}
public boolean isShow() {
return isShow;
}
private void initAnimatorIfNeed() {
if (animator != null) {
return;
}
int initTopMargin = getScreenHeight() - topOffset;
animator = ValueAnimator.ofInt(initTopMargin, 0);
animator.setDuration(animationDuration);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation, boolean isReverse) {
view.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation, boolean isReverse) {
mask.setVisibility(isReverse ? View.GONE : View.VISIBLE);
if (isReverse) {
view.setVisibility(View.GONE);
}
}
});
animator.addUpdateListener(animation -> {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) rootLayout.getLayoutParams();
layoutParams.topMargin = (int) animation.getAnimatedValue();
rootLayout.setLayoutParams(layoutParams);
});
}
private void setFloatLayoutMarginTop(int topOffset) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) bodyContainer.getLayoutParams();
layoutParams.topMargin = topOffset;
bodyContainer.setLayoutParams(layoutParams);
}
private int getScreenHeight() {
return activity.getResources().getDisplayMetrics().heightPixels;
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/view_root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="HardcodedText">
<!-- 底部蒙层 -->
<View
android:id="@+id/view_mask"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00000000"
android:visibility="gone"
tools:visibility="gone" />
<!-- 浮窗内容容器 -->
<FrameLayout
android:id="@+id/view_body_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true" />
</FrameLayout>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment