开始画房间页面功能
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
package com.qxcm.moduleutil.widget.floatingView;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.blankj.utilcode.util.BarUtils;
|
||||
import com.blankj.utilcode.util.ScreenUtils;
|
||||
|
||||
/**
|
||||
* 可拖拽悬浮
|
||||
*/
|
||||
public class FloatingMagnetView extends FrameLayout {
|
||||
|
||||
public static final int MARGIN_EDGE = 0;
|
||||
private float mOriginalRawX;
|
||||
private float mOriginalRawY;
|
||||
private float mOriginalX;
|
||||
private float mOriginalY;
|
||||
private static final int TOUCH_TIME_THRESHOLD = 150;
|
||||
private long mLastTouchDownTime;
|
||||
protected MoveAnimator mMoveAnimator;
|
||||
protected int mScreenWidth;
|
||||
private int mScreenHeight;
|
||||
private int mStatusBarHeight;
|
||||
private boolean isNearestLeft = true;
|
||||
|
||||
public FloatingMagnetView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public FloatingMagnetView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public FloatingMagnetView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mMoveAnimator = new MoveAnimator();
|
||||
mStatusBarHeight = BarUtils.getStatusBarHeight();
|
||||
setClickable(true);
|
||||
updateSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (event == null) {
|
||||
return false;
|
||||
}
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
changeOriginalTouchParams(event);
|
||||
updateSize();
|
||||
mMoveAnimator.stop();
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
updateViewPosition(event);
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
moveToEdge();
|
||||
if (isOnClickEvent()) {
|
||||
if (listener != null) {
|
||||
listener.onClick();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isOnClickEvent() {
|
||||
return System.currentTimeMillis() - mLastTouchDownTime < TOUCH_TIME_THRESHOLD;
|
||||
}
|
||||
|
||||
private void updateViewPosition(MotionEvent event) {
|
||||
setX(mOriginalX + event.getRawX() - mOriginalRawX);
|
||||
// 限制不可超出屏幕高度
|
||||
float desY = mOriginalY + event.getRawY() - mOriginalRawY;
|
||||
if (desY < mStatusBarHeight) {
|
||||
desY = mStatusBarHeight;
|
||||
}
|
||||
if (desY > mScreenHeight - getHeight()) {
|
||||
desY = mScreenHeight - getHeight();
|
||||
}
|
||||
setY(desY);
|
||||
}
|
||||
|
||||
private void changeOriginalTouchParams(MotionEvent event) {
|
||||
mOriginalX = getX();
|
||||
mOriginalY = getY();
|
||||
mOriginalRawX = event.getRawX();
|
||||
mOriginalRawY = event.getRawY();
|
||||
mLastTouchDownTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
protected void updateSize() {
|
||||
mScreenWidth = (ScreenUtils.getScreenWidth() - this.getWidth());
|
||||
mScreenHeight = ScreenUtils.getScreenHeight();
|
||||
}
|
||||
|
||||
public void moveToEdge() {
|
||||
moveToEdge(isNearestLeft());
|
||||
}
|
||||
|
||||
public void moveToEdge(boolean isLeft) {
|
||||
float moveDistance = isLeft ? MARGIN_EDGE : mScreenWidth - MARGIN_EDGE;
|
||||
mMoveAnimator.start(moveDistance, getY());
|
||||
}
|
||||
|
||||
protected boolean isNearestLeft() {
|
||||
int middle = mScreenWidth / 2;
|
||||
isNearestLeft = getX() < middle;
|
||||
return isNearestLeft;
|
||||
}
|
||||
|
||||
|
||||
protected class MoveAnimator implements Runnable {
|
||||
|
||||
private Handler handler = new Handler(Looper.getMainLooper());
|
||||
private float destinationX;
|
||||
private float destinationY;
|
||||
private long startingTime;
|
||||
|
||||
void start(float x, float y) {
|
||||
this.destinationX = x;
|
||||
this.destinationY = y;
|
||||
startingTime = System.currentTimeMillis();
|
||||
handler.post(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (getRootView() == null || getRootView().getParent() == null) {
|
||||
return;
|
||||
}
|
||||
float progress = Math.min(1, (System.currentTimeMillis() - startingTime) / 400f);
|
||||
float deltaX = (destinationX - getX()) * progress;
|
||||
float deltaY = (destinationY - getY()) * progress;
|
||||
move(deltaX, deltaY);
|
||||
if (progress < 1) {
|
||||
handler.post(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void stop() {
|
||||
handler.removeCallbacks(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void move(float deltaX, float deltaY) {
|
||||
setX(getX() + deltaX);
|
||||
setY(getY() + deltaY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
updateSize();
|
||||
moveToEdge(isNearestLeft);
|
||||
}
|
||||
|
||||
public void setListener(OnFloatingClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private OnFloatingClickListener listener;
|
||||
|
||||
public interface OnFloatingClickListener {
|
||||
void onClick();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package com.qxcm.moduleutil.widget.floatingView;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.qxcm.moduleutil.base.CommonAppContext;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
||||
/**
|
||||
* @ClassName FloatingView
|
||||
* @Description 悬浮窗管理器
|
||||
*/
|
||||
public class FloatingView implements IFloatingView {
|
||||
private View mFloatingView;
|
||||
private static volatile FloatingView mInstance;
|
||||
private WeakReference<FrameLayout> mContainer;
|
||||
@LayoutRes
|
||||
private int mLayoutId;
|
||||
private ViewGroup.LayoutParams mLayoutParams = getParams();
|
||||
|
||||
private FloatingView() {
|
||||
}
|
||||
|
||||
public static FloatingView get() {
|
||||
if (mInstance == null) {
|
||||
synchronized (FloatingView.class) {
|
||||
if (mInstance == null) {
|
||||
mInstance = new FloatingView();
|
||||
}
|
||||
}
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatingView remove() {
|
||||
orderId = 0;
|
||||
if (mFloatingView == null) {
|
||||
return this;
|
||||
}
|
||||
if (ViewCompat.isAttachedToWindow(mFloatingView) && getContainer() != null) {
|
||||
getContainer().removeView(mFloatingView);
|
||||
}
|
||||
mFloatingView = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void ensureFloatingView() {
|
||||
synchronized (this) {
|
||||
if (mFloatingView != null) {
|
||||
addViewToWindow(mFloatingView);
|
||||
return;
|
||||
}
|
||||
View view = LayoutInflater.from(CommonAppContext.getInstance()).inflate(mLayoutId, null);
|
||||
mFloatingView = view;
|
||||
view.setLayoutParams(mLayoutParams);
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
}
|
||||
});
|
||||
addViewToWindow(view);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatingView add() {
|
||||
ensureFloatingView();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatingView attach(Activity activity) {
|
||||
attach(getActivityRoot(activity));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatingView attach(FrameLayout container) {
|
||||
if (container == null || mFloatingView == null) {
|
||||
mContainer = new WeakReference<>(container);
|
||||
return this;
|
||||
}
|
||||
if (mFloatingView.getParent() == container) {
|
||||
return this;
|
||||
}
|
||||
if (getContainer() != null && mFloatingView.getParent() == getContainer()) {
|
||||
getContainer().removeView(mFloatingView);
|
||||
}
|
||||
mContainer = new WeakReference<>(container);
|
||||
container.addView(mFloatingView);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatingView detach(Activity activity) {
|
||||
detach(getActivityRoot(activity));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatingView detach(FrameLayout container) {
|
||||
if (mFloatingView != null && container != null && ViewCompat.isAttachedToWindow(mFloatingView)) {
|
||||
container.removeView(mFloatingView);
|
||||
}
|
||||
if (getContainer() == container) {
|
||||
mContainer = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView() {
|
||||
return mFloatingView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatingView customView(ViewGroup viewGroup) {
|
||||
mFloatingView = viewGroup;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatingView customView(@LayoutRes int resource) {
|
||||
mLayoutId = resource;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloatingView layoutParams(ViewGroup.LayoutParams params) {
|
||||
mLayoutParams = params;
|
||||
if (mFloatingView != null) {
|
||||
mFloatingView.setLayoutParams(params);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addViewToWindow(final View view) {
|
||||
if (getContainer() == null) {
|
||||
return;
|
||||
}
|
||||
getContainer().addView(view);
|
||||
}
|
||||
|
||||
private FrameLayout getContainer() {
|
||||
if (mContainer == null) {
|
||||
return null;
|
||||
}
|
||||
return mContainer.get();
|
||||
}
|
||||
|
||||
private FrameLayout.LayoutParams getParams() {
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT,
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT);
|
||||
params.gravity = Gravity.BOTTOM | Gravity.START;
|
||||
params.setMargins(13, params.topMargin, params.rightMargin, 500);
|
||||
return params;
|
||||
}
|
||||
|
||||
private FrameLayout getActivityRoot(Activity activity) {
|
||||
if (activity == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (FrameLayout) activity.getWindow().getDecorView().findViewById(android.R.id.content);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private boolean isExpand = true;
|
||||
|
||||
/**
|
||||
* 设置展开或者收起
|
||||
*
|
||||
* @param expand
|
||||
*/
|
||||
public void setExpand(boolean expand) {
|
||||
isExpand = expand;
|
||||
}
|
||||
|
||||
private int orderId;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.qxcm.moduleutil.widget.floatingView;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
|
||||
|
||||
public interface IFloatingView {
|
||||
|
||||
FloatingView remove();
|
||||
|
||||
FloatingView add();
|
||||
|
||||
FloatingView attach(Activity activity);
|
||||
|
||||
FloatingView attach(FrameLayout container);
|
||||
|
||||
FloatingView detach(Activity activity);
|
||||
|
||||
FloatingView detach(FrameLayout container);
|
||||
|
||||
View getView();
|
||||
|
||||
FloatingView customView(ViewGroup viewGroup);
|
||||
|
||||
FloatingView customView(@LayoutRes int resource);
|
||||
|
||||
FloatingView layoutParams(ViewGroup.LayoutParams params);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
package com.qxcm.moduleutil.widget.floatingView;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.qxcm.moduleutil.base.CommonAppContext;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
|
||||
/**
|
||||
* @ClassName FloatingView
|
||||
* @Description 悬浮窗管理器
|
||||
*/
|
||||
public class NotifyFloatingView {
|
||||
private View mFloatingView;
|
||||
private static volatile NotifyFloatingView mInstance;
|
||||
private WeakReference<FrameLayout> mContainer;
|
||||
@LayoutRes
|
||||
private int mLayoutId;
|
||||
private ViewGroup.LayoutParams mLayoutParams = getParams();
|
||||
|
||||
private NotifyFloatingView() {
|
||||
|
||||
}
|
||||
|
||||
public static NotifyFloatingView get() {
|
||||
if (mInstance == null) {
|
||||
synchronized (NotifyFloatingView.class) {
|
||||
if (mInstance == null) {
|
||||
mInstance = new NotifyFloatingView();
|
||||
}
|
||||
}
|
||||
}
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
|
||||
public NotifyFloatingView remove() {
|
||||
if (mFloatingView == null) {
|
||||
return this;
|
||||
}
|
||||
if (ViewCompat.isAttachedToWindow(mFloatingView) && getContainer() != null) {
|
||||
getContainer().removeView(mFloatingView);
|
||||
}
|
||||
mFloatingView = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
private void ensureFloatingView() {
|
||||
synchronized (this) {
|
||||
if (mFloatingView != null) {
|
||||
addViewToWindow(mFloatingView);
|
||||
return;
|
||||
}
|
||||
View view = LayoutInflater.from(CommonAppContext.getInstance()).inflate(mLayoutId, null);
|
||||
mFloatingView = view;
|
||||
view.setLayoutParams(mLayoutParams);
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
}
|
||||
});
|
||||
addViewToWindow(view);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public NotifyFloatingView add() {
|
||||
ensureFloatingView();
|
||||
handler.removeCallbacks(action);
|
||||
handler.postDelayed(action, 3000);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public NotifyFloatingView attach(Activity activity) {
|
||||
attach(getActivityRoot(activity));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public NotifyFloatingView attach(FrameLayout container) {
|
||||
if (container == null || mFloatingView == null) {
|
||||
mContainer = new WeakReference<>(container);
|
||||
return this;
|
||||
}
|
||||
if (mFloatingView.getParent() == container) {
|
||||
return this;
|
||||
}
|
||||
if (getContainer() != null && mFloatingView.getParent() == getContainer()) {
|
||||
getContainer().removeView(mFloatingView);
|
||||
}
|
||||
mContainer = new WeakReference<>(container);
|
||||
container.addView(mFloatingView);
|
||||
return this;
|
||||
}
|
||||
|
||||
public NotifyFloatingView detach(Activity activity) {
|
||||
detach(getActivityRoot(activity));
|
||||
return this;
|
||||
}
|
||||
|
||||
public NotifyFloatingView detach(FrameLayout container) {
|
||||
if (mFloatingView != null && container != null && ViewCompat.isAttachedToWindow(mFloatingView)) {
|
||||
container.removeView(mFloatingView);
|
||||
}
|
||||
if (getContainer() == container) {
|
||||
mContainer = null;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public View getView() {
|
||||
return mFloatingView;
|
||||
}
|
||||
|
||||
|
||||
public NotifyFloatingView customView(ViewGroup viewGroup) {
|
||||
mFloatingView = viewGroup;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public NotifyFloatingView customView(@LayoutRes int resource) {
|
||||
mLayoutId = resource;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public NotifyFloatingView layoutParams(ViewGroup.LayoutParams params) {
|
||||
mLayoutParams = params;
|
||||
if (mFloatingView != null) {
|
||||
mFloatingView.setLayoutParams(params);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addViewToWindow(final View view) {
|
||||
if (getContainer() == null) {
|
||||
return;
|
||||
}
|
||||
getContainer().addView(view);
|
||||
}
|
||||
|
||||
private FrameLayout getContainer() {
|
||||
if (mContainer == null) {
|
||||
return null;
|
||||
}
|
||||
return mContainer.get();
|
||||
}
|
||||
|
||||
private FrameLayout.LayoutParams getParams() {
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT,
|
||||
RelativeLayout.LayoutParams.WRAP_CONTENT);
|
||||
params.gravity = Gravity.BOTTOM | Gravity.START;
|
||||
params.setMargins(13, params.topMargin, params.rightMargin, 500);
|
||||
return params;
|
||||
}
|
||||
|
||||
private FrameLayout getActivityRoot(Activity activity) {
|
||||
if (activity == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (FrameLayout) activity.getWindow().getDecorView().findViewById(android.R.id.content);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Handler handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private Runnable action = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotifyFloatingView.get().remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user